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);
}

 

Posted on 2010-04-16 10:18  我不是牛人  阅读(1130)  评论(0编辑  收藏  举报