zoukankan      html  css  js  c++  java
  • MFC学习(一)

    CObject

     

    说到MFC学习就不得不说CObject 类,因为它是MFC大多数类的基类。所以有必要从“头”学起。

     

     

    构造函数

    CObject 默认 构造函数.
    CObject 拷贝 构造.
    operator delete 特殊 delete 操作.
    operator new 特殊 new 操作.

    诊断函数

    AssertValid 检测 this object's 完整性.
    Dump 泄露诊断函数.

    串行化

    IsSerializable 检测是否支持串行化.
    Serialize 加载或保存对象从/到档案.

    类型识别

    GetRuntimeClass Returns the CRuntimeClass structure corresponding to this object's class.
    IsKindOf Tests this object's relationship to a given class.

    接下来,我们分别从MFC源代码及测试源代码及测试结果的角度分析。

    CObject();

    protected CObject(void);    // 类声明

    _AFX_INLINE CObject::CObject() // 仅是一个空的实现
     { }

    CObject类是一个抽象类,不能直接new 对象。

    例如:

    CObject obj;   // 这样写是无法编译的

    默认构造函数是protected的,所以无法直接产生对象。仅能在其子类中产生。

    CObject( const CObject& objectSrc );

    private CObject(class CObject const &);

    private operator=(class CObject const &);

    这两个函数没有实现,只是声明为私有的。这样如果在了类中没有重载就不能进行拷贝操作。

    CObject::CObject CObject( ); CObject( const CObject& objectSrc ); 参数: objectSrc 另一个CObject对象的参考。 说明:上述函数为标准的CObject构造函数。通过派生类的构造函数自动调用该函数的缺省形式。如果你的类可串行化(它引入了IMPLEMENT_SERIAL宏),那么在类的派生中必须使用缺省的构造函数(即没有参数的构造函数)。若不需要缺省的构造函数,请事先声明私有的和受保护的“空”构造函数。标准C 缺省类拷贝构造函数进行的是成员对成员的拷贝。如果需要你自己类的拷贝构造函数但现在没有,那么私有的CObject拷贝构造函数的存在将保证编译器发出错误消息。因此,若你的类需要这种能力,就必须提供拷贝构造函数。

    CObject::CObject CObject( ); CObject( const CObject& objectSrc ); 参数: objectSrc 另一个CObject对象的参考。 说明:上述函数为标准的CObject构造函数。通过派生类的构造函数自动调用该函数的缺省形式。如果你的类可串行化(它引入了IMPLEMENT_SERIAL宏),那么在类的派生中必须使用缺省的构造函数(即没有参数的构造函数)。若不需要缺省的构造函数,请事先声明私有的和受保护的“空”构造函数。如果需要更多信息,请参阅联机文档“Visual C 程序员指南”中的“CObject类主题”。标准C 缺省类拷贝构造函数进行的是成员对成员的拷贝。如果需要你自己类的拷贝构造函数但现在没有,那么私有的CObject拷贝构造函数的存在将保证编译器发出错误消息。因此,若你的类需要这种能力,就必须提供拷贝构造函数。

    Object.h

    class AFX_NOVTABLE CObject
    {
    public:

    // Object model (types, destruction, allocation)
     virtual CRuntimeClass* GetRuntimeClass() const;
     virtual ~CObject() = 0;  // virtual destructors are necessary

     // Diagnostic allocations
     void* PASCAL operator new(size_t nSize);
     void* PASCAL operator new(size_t, void* p);
     void PASCAL operator delete(void* p);
    #if _MSC_VER >= 1200
     void PASCAL operator delete(void* p, void* pPlace);
    #endif

    #if defined(_DEBUG) && !defined(_AFX_NO_DEBUG_CRT)
     // for file name/line number tracking using DEBUG_NEW
     void* PASCAL operator new(size_t nSize, LPCSTR lpszFileName, int nLine);
    #if _MSC_VER >= 1200
     void PASCAL operator delete(void *p, LPCSTR lpszFileName, int nLine);
    #endif
    #endif

     // Disable the copy constructor and assignment by default so you will get
     //   compiler errors instead of unexpected behaviour if you pass objects
     //   by value or assign objects.
    protected:
     CObject();
    private:
     CObject(const CObject& objectSrc);              // no implementation
     void operator=(const CObject& objectSrc);       // no implementation

    // Attributes
    public:
     BOOL IsSerializable() const;
     BOOL IsKindOf(const CRuntimeClass* pClass) const;

    // Overridables
     virtual void Serialize(CArchive& ar);

    #if defined(_DEBUG) || defined(_AFXDLL)
     // Diagnostic Support
     virtual void AssertValid() const;
     virtual void Dump(CDumpContext& dc) const;
    #endif

    // Implementation
    public:
     static const CRuntimeClass classCObject;
    #ifdef _AFXDLL
     static CRuntimeClass* PASCAL _GetBaseClass();
     static CRuntimeClass* PASCAL GetThisClass();
    #endif
    };

    Object.cpp


    // special runtime-class structure for CObject (no base class)
    const struct CRuntimeClass CObject::classCObject =
     { "CObject", sizeof(CObject), 0xffff, NULL, NULL, NULL };

    CRuntimeClass* CObject::GetRuntimeClass() const
    {
     return _RUNTIME_CLASS(CObject);
    }

    #ifdef _AFXDLL
    CRuntimeClass* PASCAL CObject::_GetBaseClass()
    {
     return NULL;
    }
    CRuntimeClass* PASCAL CObject::GetThisClass()
    {
     return _RUNTIME_CLASS(CObject);
    }
    #endif

    BOOL CObject::IsKindOf(const CRuntimeClass* pClass) const
    {
     ENSURE(this != NULL);
     // it better be in valid memory, at least for CObject size
     ASSERT(AfxIsValidAddress(this, sizeof(CObject)));

     // simple SI case
     CRuntimeClass* pClassThis = GetRuntimeClass();

     ENSURE(pClassThis);
     return pClassThis->IsDerivedFrom(pClass);
    }

    CObject* AFX_CDECL AfxDynamicDownCast(CRuntimeClass* pClass, CObject* pObject)
    {
     if (pObject != NULL && pObject->IsKindOf(pClass))
      return pObject;
     else
      return NULL;
    }

    #ifdef _DEBUG
    CObject* AFX_CDECL AfxStaticDownCast(CRuntimeClass* pClass, CObject* pObject)
    {
     ASSERT(pObject == NULL || pObject->IsKindOf(pClass));
     return pObject;
    }
    #endif

    /////////////////////////////////////////////////////////////////////////////
    // Diagnostic Support

    #ifdef _DEBUG
    void AFXAPI AfxAssertValidObject(const CObject* pOb,
     LPCSTR lpszFileName, int nLine)
    {
     if (pOb == NULL)
     {
      TRACE(traceAppMsg, 0, "ASSERT_VALID fails with NULL pointer.\n");
      if (AfxAssertFailedLine(lpszFileName, nLine))
       AfxDebugBreak();
      return;     // quick escape
     }
     if (!AfxIsValidAddress(pOb, sizeof(CObject)))
     {
      TRACE(traceAppMsg, 0, "ASSERT_VALID fails with illegal pointer.\n");
      if (AfxAssertFailedLine(lpszFileName, nLine))
       AfxDebugBreak();
      return;     // quick escape
     }

     // check to make sure the VTable pointer is valid
     ASSERT(sizeof(CObject) == sizeof(void*));
     if (!AfxIsValidAddress(*(void**)pOb, sizeof(void*), FALSE))
     {
      TRACE(traceAppMsg, 0, "ASSERT_VALID fails with illegal vtable pointer.\n");
      if (AfxAssertFailedLine(lpszFileName, nLine))
       AfxDebugBreak();
      return;     // quick escape
     }

     if (!AfxIsValidAddress(pOb, pOb->GetRuntimeClass()->m_nObjectSize, FALSE))
     {
      TRACE(traceAppMsg, 0, "ASSERT_VALID fails with illegal pointer.\n");
      if (AfxAssertFailedLine(lpszFileName, nLine))
       AfxDebugBreak();
      return;     // quick escape
     }
     pOb->AssertValid();
    }

    void CObject::AssertValid() const
    {
     ASSERT(this != NULL);
    }

    void CObject::Dump(CDumpContext& dc) const
    {
     dc << "a " << GetRuntimeClass()->m_lpszClassName <<
      " at " << (void*)this << "\n";

     UNUSED(dc); // unused in release build
    }
    #endif //_DEBUG

    ////////////////////////////////////////////////////////////////////////////
    // Allocation/Creation

    CObject* CRuntimeClass::CreateObject()
    {
     ENSURE(this);

     if (m_pfnCreateObject == NULL)
     {
      TRACE(traceAppMsg, 0,
       _T("Error: Trying to create object which is not ")
       _T("DECLARE_DYNCREATE \nor DECLARE_SERIAL: %hs.\n"),
       m_lpszClassName);
      return NULL;
     }

     CObject* pObject = NULL;
     TRY
     {
      pObject = (*m_pfnCreateObject)();
     }
     END_TRY

     return pObject;
    }

    ////////////////////////////////////////////////////////////////////////////
    // Class loader & class serialization

    BOOL CObject::IsSerializable() const
    {
     return (GetRuntimeClass()->m_wSchema != 0xffff);
    }

    void AFXAPI AfxClassInit(CRuntimeClass* pNewClass)
    {
     AFX_MODULE_STATE* pModuleState = AfxGetModuleState();
     AfxLockGlobals(CRIT_RUNTIMECLASSLIST);
     pModuleState->m_classList.AddHead(pNewClass);
     AfxUnlockGlobals(CRIT_RUNTIMECLASSLIST);
    }

  • 相关阅读:
    1、购买阿里云服务器
    struts2页面乱码解决方法
    struts第一次编写怎么都无法跳转页面
    时间转换与map集合
    struts2addActionError 、addFieldError、addActionMessage方法
    struts2基本流程
    struts2自定义类型转换器
    jsp聊天窗口随笔
    conn!=null与conn.isClosed的区别
    应用表单隐藏域进行提交
  • 原文地址:https://www.cnblogs.com/cplusplus/p/1713278.html
Copyright © 2011-2022 走看看