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);
}
                    
                
                
            
        
浙公网安备 33010602011771号