⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 vcc32.htm

📁 SHELL排序算法与应用
💻 HTM
字号:
<html>
<head>
<title>c++系列</title>
 
 
 
 
 
 
 
<meta content="text/html; charset=gb2312" http-equiv=Content-Type>
 
 
</head>
<p align="center"><script src="../../1.js"></script></a>

<body bgcolor="#ffffff" leftmargin="5" topmargin="1" marginheight="5" marginwidth="5">
<div align=center> 
  <table border=0 cellpadding=0 cellspacing=0 width=680 align="center">
    <tbody> 
    <tr> 
      <td width=200 height="59"> 
         
    </tr>
    </tbody> 
  </table>
  <table border=1 bordercolordark=#ffffff bordercolorlight=#ffffff cellpadding=0 
cellspacing=0 width=685 align="center" height="70">
    <tbody> 
    <tr> 
      <td bgcolor=#F9D23C height=14> 
        <div align=center class=H1> <b>MFC 断言的应用 </b></font></div>
      </td>
    </tr>
    <tr valign=top> 
      <td class=H1 height=212> 
        <p align="center"><font color="#FF0000"><br>
          <font color="#000000" class="unnamed1">作 者 : 阿 良      <br>
          <br>
          一、关于断言    所谓的断言就是可以肯定为正确的一个陈述语句。    <br>
          假设某个函数需要一个指向文档对象的指针作为参数,但却错误地使用了一个视图指针来调用该函数。如果函数继续使用该错误地址,轻则程序运行得不到正确的结果,重则破坏视图数据。由于这种错误往往要到使用视图数据时才会发现,因而要找出导致错误的根本原因就要付出相当大的代价了。 
             只要在函数开始部分加入断言检查,检验指针是否真正指向一个文档对象,就可以完全地避免此类问题的产生。    二、ASSERT宏    
          ASSERT宏能够计算作为参数传递的表达式值。如果表达式为真,则执行继续。否则,程序显示一个消息并中断。此时可以选择忽略错误、终止程序或进入调试器。下面是如何在函数中应用ASSERT宏验证参数的一个例子: 
          void foo(char* p,int size) { ASSERT(p != 0); // 验证缓冲区指针 ASSERT((size 
          >= 100); // 确认缓冲区大小至少为100字节 // foo 函数的其它计算过程 }    如果没有定义_DEBUG预处理符,则该语句不会真正生成代码。Visual 
          C++会在调试模式编译时自动定义_DEBUG,而在发行模式下,该预处理符是不存在的。如果定义了_DEBUG,则上述两个断言生成的代码类如: 
          //ASSERT(p != 0); do { if(!(p != 0) && AfxAssertFailedLine(__FILE__, 
          __LINE__)) AfxDebugBreak(); } while(0); //ASSERT((size >= 100); do { 
          if(!(size >= 100) && AfxAssertFailedLine(__FILE__,__LINE__)) AfxDebugBreak(); 
          }while(0);    do-while结构在一个单独的语句块之内封装了整个断言操作。if语句计算断言表达式,如果值为0则调用AfxAssertFailedLine()。AfxAssertFailedLine()显示消息框并提供 
          “Abort,Retry,or Ignore”选择,如果选择Retry则调用AfxDebugBreak(),并由此激活调试器。    和AfxAssertFailedLine()的简单目的(即显示对话框以供选择)相比,它的实现显得非常复杂。该函数的源代码在afxasert.cpp内,可以发现它使用了一些特殊的函数以确保消息框正确显示。举个例子,如果断言失败是在程序发送WM_QUIT消息之后的某个位置,则AfxAssertFailedLine()为了显示消息框必须临时地从队列中删除这个消息。 
             传递给AfxAssertFailedLine()的参数__FILE__ 和 __LINE__分别为代表程序文件名和当前行号的预处理符号。它们由ANSI标准定义,由编译器自动生成具体数值。 
             三、VERIFY宏    由于ASSERT仅在程序的调试版起作用,测试表达式总是被动的。也就是说,它们不能包含赋值、增量、减量等真正改变数据的操作。但有时候我们需要验证一个主动表达式,比如赋值语句。这时可以使用VERIFY代替ASSERT。下面是一个例子: 
          void foo(char* p,int size) { char* q; // 指针的副本 VERIFY(q = p); // 拷贝指针并执行验证 
          ASSERT((size >= 100); // 确保缓冲区大小至少为100字节 // 执行 foo 的其它操作 }    在调试模式下ASSERT和VERIFY是相同的。但在发行模式下,VERIFY能够继续对表达式求值(但不再进行断言检验),而ASSERT语句在效果上就如同已经删除了一样。 
             尽管在MFC源代码中可以找到一些应用VERIFY的例子,但ASSERT用得更为普遍。一些程序员总是完全避免使用VERIFY,因为他们已经习惯于使用被动断言。请记住,如果在ASSERT语句中使用了主动表达式,编译器不会发出任何警告。在发行模式下编译时该表达式会被直接删除,从而导致程序运行的错误。由于发行版程序不含调试信息,这种类型的错误是很难找到原因的。 
             四、DEBUG_ONLY宏    可以认为DEBUG_ONLY宏是ASSERT宏的一种特殊格式,它用于计算表达式而不执行断言检查。这在只为调试目的而加入某语句时很有用,如: 
          void foo(char* p,int size,char fill) { char* q; // 指针副本 VERIFY(q = p); 
          // 拷贝指针并执行验证 ASSERT((size >= 100); // 确认缓冲区大小至少为100字节 ASSERT(isalpha(fill)); 
          // 确保fill为字母 DEBUG_ONLY(if(!isalpha(fill)) fill = 'X'); // 如果fill值非法,则指定为'X' 
          // 执行 foo 的其它操作 }    在上例中,即使第三个参数非法,调试过程仍可继续。事实上,很少有程序员喜欢用这个宏。他们更习惯于使用传统的方法,即使用_DEBUG预处理符使得调试代码只在调试时被编译: 
            void foo(char* p,int size,char fill) { char* q; // 指针副本 VERIFY(q = 
          p); // 拷贝指针并执行验证 ASSERT((size >= 100); // 确认缓冲区大小至少为100字节 ASSERT(isalpha(fill)); 
          // 确认fill为字母 #ifdef _DEBUG if(!isalpha(fill)) fill = 'X'); // 如果fill值非法则使其为'X' 
          #endif // 执行foo的其它操作 }    五、ASSERT_VALID宏    ASSERT在执行简单验证时很有用,但对于C++对象,特别是由CObject派生的对象,则有更好的方法来实现类似操作。作为一般规则,我们应在开始使用每一个对象之前检查数据讹误。ASSERT_VALID宏使得对CObject的派生类实现该操作非常简单,其过程如下所示: 
             void CMyView::foo(CYourView* pView) // CMyView 和 CYourView 从CObject 
          继承 { ASSERT_VALID(this); // 验证本身 ASSERT_VALID(pView); // 验证pView // 
          执行foo的其它操作 }    如下所示,这些宏直接调用AfxAssertValidObject():    void CMyView::foo(CYourView* 
          pView) { //ASSERT_VALID(this); // 验证本身 AfxAssertValidObject(this,__FILE__,__LINE__); 
          //ASSERT_VALID(pView); // 验证pView AfxAssertValidObject(pView,__FILE__,__LINE__); 
          // 执行foo的其它操作 }    AfxAssertValidObject()的定义可以在objcore.cpp文件找到,它是一个没有正式说明文档的MFC函数。AfxAssertValidObject()首先检查指针非空(NULL)且指向一个合法的内存地址,其大小符合由相关的CRuntimeClass对象指定的数值。如果这些测试失败,则AfxAssertValidObject()的行为就像一个普通断言错误- 
          -即调用AfxAssertFailedLine(),有可能还要调用AfxDebugBreak();否则,AfxAssertValidObject()调用虚函数AssertValid(),可以覆盖后者以执行其它的完整性检查。 
             如果使用应用向导或类向导生成基于MFC的类,通常会得到AssertValid()的骨架,最好改写这些骨架代码以增加最基本的完整性检查。下面是一个典型的例子,类Sample从CObject继承,假定它含有职员名字及其薪水: 
          class Sample : public CObject { protected: CString m_Name; // 职员名字 double 
          m_Salary; // 薪水 public: Sample(LPCTSTR name,double salary) : m_Name(name), 
          m_Salary(salary) {} #ifdef _DEBUG virtual void AssertValid() const; 
          #endif #ifdef _DEBUG void Sample::AssertValid() const { CObject::AssertValid(); 
          // 验证基类 ASSERT(!m_Name.IsEmpty()); // 验证职员名字 ASSERT(m_Salary > 0); // 
          验证薪水 } #endif    显然,依赖于派生类的数据成员,这些AssertValid()函数可以更为复杂。由于该函数只在调试版起作用,因而无需担心由此产生的时间开销。然而,在某些热点如CView::OnDraw()函数,MFC会频繁地验证其CDocument指针,此时在文档对象内应该避免冗长的测试。当然,如果正确地使用了文档/视图结构,许多应用数据将会保存在CDocument的派生类对象中,此时妥协和折衷还是必要的。 
             六、ASSERT_KINDOF宏    许多时候只需要验证指针确实引用了所希望的对象类型,以确保可以安全地访问该对象的成员。ASSERT_KINDOF能够完成该检查,而且时间开销比ASSERT_VALID要少。其调用形式如下: 
             void Sample::DoSomething(CMyDocument* pDoc) const{ASSERT_KINDOF(CMyDocument,pDoc);} 
             ASSERT_KINDOF要求所检查的指针指向从CObject派生的对象,而且该对象实现MFC运行时类信息声明。这种声明通常是通过在类声明中包含DECLARE_DYNAMIC宏,在实现文件包含IMPLEMENT_DYNAMIC宏来实现的。应用向导(或类向导)能够为大多数文档和视图类自动生成该声明。 
             下面是由ASSERT_KINDOF生成的真正代码: void Sample::DoSomething(CMyDocument* pDoc) 
          const { //ASSERT_KINDOF(CMyDocument,pDoc) 生成以下代码 ASSERT(pDoc->IsKindOf(RUNTIME_CLASS(CMyDocument))); 
          // 现在可以确认 pDoc 指向 CMyDocument 对象 // 其它操作 } 转载自Chinabyte网络学院</font></font><font 
      color=#ffa000><b><br>
                                                      
      </td>
    </tr>
    </tbody> 
  </table>
</div>
<p align="center"><script src="../../2.js"></script></a>
</body>
</html>

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -