AssertValid和Dump 这两个函数的作用

本文详细介绍了AssertValid函数用于验证对象内部状态的有效性,并通过断言确保程序的健壮性。同时,阐述了Dump函数的功能及其在调试过程中的应用,包括如何重写以提供更多调试信息。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

AssertValid函数是用来判断表达式的合法性或正确性,如果不正确或不合法则终止程序并返回相应的提示信息  
  如AssertValid(t==0);//用来判断t是否等于0,如果t!=0则终止程序  
  Dump函数一般用来显示debug信息的,其函数中的内容一般在debug时,在debug窗口中才能看到。

CObject::AssertValid   成员函数提供对对象内部状态的运行时检查。尽管从   CObject   派生类时不需要重写   AssertValid,但可以通过重写使您的类更安全可靠。AssertValid   应在对象的所有成员变量上执行断言,以验证它们包含有效值。例如,它应检查指针成员变量不为   NULL。  
  下面的示例显示如何声明   AssertValid   函数:  
  class   CPerson   :   public   CObject  
  {  
  protected:  
        CString   m_strName;  
        float       m_salary;  
  public:  
  #ifdef   _DEBUG  
        virtual   void   AssertValid()   const;       //   Override  
  #endif  
        //   ...  
  };  
  当重写   AssertValid   时,在执行您自己的检查之前请调用   AssertValid   的基类版本。然后使用   ASSERT   宏检查您的派生类特有的成员,如下所示:     
  #ifdef   _DEBUG  
  void   CPerson::AssertValid()   const  
  {  
        //   call   inherited   AssertValid   first  
        CObject::AssertValid();  
   
        //   check   CPerson   members...  
        ASSERT(   !m_strName.IsEmpty());   //   Must   have   a   name  
        ASSERT(   m_salary   >   0   );   //   Must   have   an   income  
  }  
  #endif  
  如果任何成员变量存储对象,则可以使用   ASSERT_VALID   宏测试它们的内部有效性(如果它们的类重写了   AssertValid)。  
  例如,考虑   CMyData   类,该类在其成员变量之一中存储了一个   CObList。CObList   变量   m_DataList   存储了一个   CPerson   对象的集合。CMyData   的简化声明如下所示:  
   
  class   CMyData   :   public   CObject  
  {  
        //   Constructor   and   other   members   ...  
        protected:  
              CObList*   m_pDataList;  
        //   Other   declarations   ...  
        public:  
  #ifdef   _DEBUG  
              virtual   void   AssertValid(   )   const;   //   Override  
  #endif  
        //   Etc.   ...  
  };  
  CMyData   中重写的   AssertValid   如下所示:  
   
  #ifdef   _DEBUG  
  void   CMyData::AssertValid(   )   const  
  {  
        //   Call   inherited   AssertValid  
        CObject::AssertValid(   );  
        //   Check   validity   of   CMyData   members  
        ASSERT_VALID(   m_pDataList   );  
        //   ...  
  }  
  #endif  
  CMyData   使用   AssertValid   机制测试其数据成员中存储的对象的有效性。CMyData   中重写的   AssertValid   为它自己的   m_pDataList   成员变量调用   ASSERT_VALID   宏。     
  因为   CObList   类也重写   AssertValid,所以有效性测试不在该级别停止。该重写对列表的内部状态执行附加有效性测试。因此,对   CMyData   对象的有效性测试将导致对存储的   CObList   列表对象内部状态的附加有效性测试。     
  再多进行一些操作,还可以添加对存储在列表中的   CPerson   对象的有效性测试。可以从   CObList   派生   CPersonList   类,并重写   AssertValid。在重写中可调用   CObject::AssertValid,然后循环访问列表,在列表中存储的每个   CPerson   对象上调用   AssertValid。本主题开始所示的   CPerson   类已重写了   AssertValid。     
  当为调试生成时,这是一种功能极强的机制。当接着为发布生成时,该机制自动关闭。     
  AssertValid   的限制  
  给定类的   AssertValid   函数的用户应注意该函数的限制。触发的断言指示对象一定有误,并且执行将暂停。但是,缺少断言只指示未找到任何问题,并不保证对象是好的。  

   当从   CObject   派生类时,在使用   DumpAllObjectsSince   将对象转储到“输出”窗口时,可以重写   Dump   成员函数以提供附加信息。  
  Dump   函数将对象的成员变量的文本化表示形式写入转储上下文   (CDumpContext)。转储上下文类似于   I/O   流。可以使用插入运算符   (<<)   向   CDumpContext   发送数据。     
  重写   Dump   函数时,应先调用   Dump   的基类版本以转储基类对象的内容。然后为派生类的每个成员变量输出文本化说明和值。  
   
  Dump   函数的声明如下所示:  
   
  class   CPerson   :   public   CObject  
  {  
  public:  
  #ifdef   _DEBUG  
        virtual   void   Dump(   CDumpContext&   dc   )   const;  
  #endif  
   
        CString   m_firstName;  
        CString   m_lastName;  
        //   And   so   on...  
  };  
  由于对象转储只在调试程序时有意义,所以   Dump   函数的声明用   #ifdef   _DEBUG   /   #endif   块括起来。     
  在下面的示例中,Dump   函数先为其基类调用   Dump   函数。然后,它将每个成员变量的简短说明与该成员的值一起写入诊断流。  
   
  #ifdef   _DEBUG  
  void   CPerson::Dump(   CDumpContext&   dc   )   const  
  {  
        //   Call   the   base   class   function   first.  
        CObject::Dump(   dc   );  
   
        //   Now   do   the   stuff   for   our   specific   class.  
        dc   <<   "last   name:   "   <<   m_lastName   <<   "/n"  
              <<   "first   name:   "   <<   m_firstName   <<   "/n";  
  }  
  #endif  
  必须提供   CDumpContext   参数以指定转储输出的目的地。MFC   的“Debug”版本提供名为   afxDump   的预定义   CDumpContext   对象,它将输出发送到调试器。  
   
  CPerson*   pMyPerson   =   new   CPerson;  
  //   Set   some   fields   of   the   CPerson   object.  
  //...  
  //   Now   dump   the   contents.  
  #ifdef   _DEBUG  
  pMyPerson->Dump(   afxDump   );  
  #endif  
  在   MFC   程序中,可以使用   DumpAllObjectsSince   转储有关堆中尚未释放的所有对象的说明。DumpAllObjectsSince   转储自上个   CMemoryState::Checkpoint   以来分配的所有对象。如果未发生   Checkpoint   调用,则   DumpAllObjectsSince   将转储当前在内存中的所有对象和非对象。  
   
  注意       必须先启用诊断跟踪,然后才能使用   MFC   对象转储。  
  注意       程序退出时   MFC   将自动转储所有泄漏的对象,因此不必创建代码在该点转储对象。  
  以下代码通过比较两个内存状态来测试内存泄漏,并在检测到泄漏时转储所有对象:  
   
  if(   diffMemState.Difference(   oldMemState,   newMemState   )   )  
  {  
        TRACE(   "Memory   leaked!/n"   );  
        diffMemState.DumpAllObjectsSince();  
  }  
  转储的内容如下所示:  
   
  Dumping   objects   ->  
   
  {5}   strcore.cpp(80)   :   non-object   block   at   $00A7521A,   9   bytes   long  
  {4}   strcore.cpp(80)   :   non-object   block   at   $00A751F8,   5   bytes   long  
  {3}   strcore.cpp(80)   :   non-object   block   at   $00A751D6,   6   bytes   long  
  {2}   a   CPerson   at   $51A4  
   
  Last   Name:   Smith  
  First   Name:   Alan  
  Phone   #:   581-0215  
   
  {1}   strcore.cpp(80)   :   non-object   block   at   $00A7516E,   25   bytes   long  
转自:http://control.blog.sina.com.cn/admin/article/article_add.php

#include "pch.h" #include "framework.h" // SHARED_HANDLERS 可以在实现预览、缩略图搜索筛选器句柄的 // ATL 项目中进行定义,并允许与该项目共享文档代码。 #ifndef SHARED_HANDLERS #include "MFC3DApp.h" #endif #include "MFC3DAppDoc.h" #include "MFC3DAppView.h" #ifdef _DEBUG #define new DEBUG_NEW #endif // CMFC3DAppView IMPLEMENT_DYNCREATE(CMFC3DAppView, CView) BEGIN_MESSAGE_MAP(CMFC3DAppView, CView) // 标准打印命令 ON_COMMAND(ID_FILE_PRINT, &CView::OnFilePrint) ON_COMMAND(ID_FILE_PRINT_DIRECT, &CView::OnFilePrint) ON_COMMAND(ID_FILE_PRINT_PREVIEW, &CMFC3DAppView::OnFilePrintPreview) ON_WM_CONTEXTMENU() ON_WM_RBUTTONUP() ON_WM_LBUTTONDOWN() ON_WM_LBUTTONUP() END_MESSAGE_MAP() // CMFC3DAppView 构造/析构 CMFC3DAppView::~CMFC3DAppView() { } BOOL CMFC3DAppView::PreCreateWindow(CREATESTRUCT& cs) { // TODO: 在此处通过修改 CREATESTRUCT cs 来修改窗口类或样式 return CView::PreCreateWindow(cs); } // CMFC3DAppView 绘制 void CMFC3DAppView::OnDraw(CDC* pDC) { CMFC3DAppDoc* pDoc = GetDocument(); ASSERT_VALID(pDoc); if (!pDoc) return; for (const auto& cube : m_cubes) { TwoXiece(cube, pDC); } } void CMFC3DAppView::TwoXiece(const std::array<float, 8 * 3>& vertices, CDC* pDC) { // 获取客户区域 CRect clientRect; GetClientRect(&clientRect); // 投影后的顶点坐标 CPoint projected[8]; double cosTheta = cos(m_b); double sinTheta = sin(m_b); for (int i = 0; i < 8; ++i) { double x = vertices[i * 3 + 0]; double y = vertices[i * 3 + 1]; double z = vertices[i * 3 + 2]; // 斜二测投影公式 double px = x + z * m_t * cosTheta; double py = y + z * m_t * sinTheta; // 转换为屏幕坐标 projected[i].x = (int)(px); projected[i].y = (int)(py); } CPen pen(PS_SOLID, 1, RGB(0, 0, 0)); CPen* pOldPen = pDC->SelectObject(&pen); // 立方体边的索引对 static int edges[12][2] = { {0, 1}, {1, 2}, {2, 3}, {3, 0}, {4, 5}, {5, 6}, {6, 7}, {7, 4}, {0, 4}, {1, 5}, {2, 6}, {3, 7} }; // 绘制立方体边 for (int i = 0; i < 12; ++i) { int a = edges[i][0]; int b = edges[i][1]; pDC->MoveTo(projected[a]); pDC->LineTo(projected[b]); } pDC->SelectObject(pOldPen); } // CMFC3DAppView 打印 void CMFC3DAppView::OnFilePrintPreview() { #ifndef SHARED_HANDLERS AFXPrintPreview(this); #endif } BOOL CMFC3DAppView::OnPreparePrinting(CPrintInfo* pInfo) { // 默认准备 return DoPreparePrinting(pInfo); } void CMFC3DAppView::OnBeginPrinting(CDC* /*pDC*/, CPrintInfo* /*pInfo*/) { // TODO: 添加额外的打印前进行的初始化过程 } void CMFC3DAppView::OnEndPrinting(CDC* /*pDC*/, CPrintInfo* /*pInfo*/) { // TODO: 添加打印后进行的清理过程 } void CMFC3DAppView::OnRButtonUp(UINT /* nFlags */, CPoint point) { ClientToScreen(&point); OnContextMenu(this, point); } void CMFC3DAppView::OnContextMenu(CWnd* /* pWnd */, CPoint point) { #ifndef SHARED_HANDLERS theApp.GetContextMenuManager()->ShowPopupMenu(IDR_POPUP_EDIT, point.x, point.y, this, TRUE); #endif } void CMFC3DAppView::OnLButtonDown(UINT nFlags, CPoint point) { CView::OnLButtonDown(nFlags, point); m_startPoint = point; } void CMFC3DAppView::OnLButtonUp(UINT nFlags, CPoint point) { CView::OnLButtonUp(nFlags, point); m_endPoint = point; // 固定大小的正方体 float size = 50.0f; // 固定大小 // 使用起点作为正方体的中心点 float centerX = m_startPoint.x; float centerY = m_startPoint.y; // 创建新的正方体顶点 std::array<float, 8 * 3> newCube = { centerX - size, centerY - size, 0, centerX + size, centerY - size, 0, centerX + size, centerY + size, 0, centerX - size, centerY + size, 0, centerX - size, centerY - size, size * 2, centerX + size, centerY - size, size * 2, centerX + size, centerY + size, size * 2, centerX - size, centerY + size, size * 2 }; // 添加新正方体到列表 m_cubes.push_back(newCube); // 刷新视图 Invalidate(); } #ifdef _DEBUG void CMFC3DAppView::AssertValid() const { CView::AssertValid(); } void CMFC3DAppView::Dump(CDumpContext& dc) const { CView::Dump(dc); } CMFC3DAppDoc* CMFC3DAppView::GetDocument() const // 非调试版本是内联的 { ASSERT(m_pDocument->IsKindOf(RUNTIME_CLASS(CMFC3DAppDoc))); return (CMFC3DAppDoc*)m_pDocument; } #endif //_DEBUG #pragma once #include "afxwin.h" #include <vector> #include <array> class CMFC3DAppDoc; class CMFC3DAppView : public CView { protected: // 仅从序列化创建 DECLARE_DYNCREATE(CMFC3DAppView) // 特性 public: CMFC3DAppDoc* GetDocument() const; // 操作 public: // 重写 public: virtual void OnDraw(CDC* pDC); // 重写以绘制该视图 virtual BOOL PreCreateWindow(CREATESTRUCT& cs); protected: virtual BOOL OnPreparePrinting(CPrintInfo* pInfo); virtual void OnBeginPrinting(CDC* pDC, CPrintInfo* pInfo); virtual void OnEndPrinting(CDC* pDC, CPrintInfo* pInfo); // 实现 public: virtual ~CMFC3DAppView(); #ifdef _DEBUG virtual void AssertValid() const; virtual void Dump(CDumpContext& dc) const; #endif protected: // 生成的消息映射函数 protected: afx_msg void OnFilePrintPreview(); afx_msg void OnRButtonUp(UINT nFlags, CPoint point); afx_msg void OnContextMenu(CWnd* pWnd, CPoint point); afx_msg void OnLButtonDown(UINT nFlags, CPoint point); afx_msg void OnLButtonUp(UINT nFlags, CPoint point); DECLARE_MESSAGE_MAP() private: float m_t = 0.5f; float m_b = 45.0f * 3.1415926f / 180.0f; // 默认角度 45 度 // 存储每个正方体的顶点坐标 std::vector<std::array<float, 8 * 3>> m_cubes; // 鼠标按下释放的位置 CPoint m_startPoint; CPoint m_endPoint; // 斜二测投影函数 void TwoXiece(const std::array<float, 8 * 3>& vertices, CDC* pDC); }; #ifndef _DEBUG // CMFC3DAppView 在 debug 中调试版本 inline CMFC3DAppDoc* CMFC3DAppView::GetDocument() const { return reinterpret_cast<CMFC3DAppDoc*>(m_pDocument); } #endif 这些代码完成一个正方体的斜二侧投影吗、
最新发布
05-30
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值