结合effective c++看MFC的类设计

/
// class CObject is the root of all compliant objects
//
//CObject 是MFC类的最顶层的基类,主要包括以下几种支持:
//  串行化支持,CRun-time类信息(RTTI),类型诊断输出,容器类的兼容
//  CObject不支持多继承,只能从一个CObject类中继承,并且还要放在最左边,即第一个嘛,
//  当然除了CObject类,从结构体,非CObject类中还是可以多继承的,这在语言上是怎么实现这个控制的
// 
//
//注意:
//  1. CObject的析构函数被声明为virtual,为什么必须把它声明为虚函数
//   解答:effective c++ sec-edit中条款14:确定基类有虚析构函数,原因是C++标准中这样描述,通过基类的指针来
//   删除派生类对象时,如果基类没有提供虚析构函数,那么情况将不可预知.多数情况下,派生类的析构函数是不会被
//   调用的,所有一般要用做基类的类,都会提供一个虚析构函数
//
//  2. 构造函数设为protected,为什么?这样不能直接构造CObject对象,而继承类是可以对基类构造函数进行调用
//   为什么不能给用户构造CObject对象呢?难道是因为这个基类永远都不可能用来构造对象
//   这个又跟一般的非虚函数是一样的,如果是一个非虚函数,那么是静态绑定,那是指针的静态类型是什么,调用的就是
//   哪个类型的成员函数
//
//  3. 设计了两个非虚函数public:  BOOL IsSerializable() const;
//   public:  BOOL IsKindOf(const CRuntimeClass* pClass) const;
//   那就是说明这两个函数对所有从CObject中派生出来的类这两个操作都是一样的,这个恐怕由于DECLARE_DYNAMIC宏确定了
//   就确定了
//
//  4. 设计了一个类属性public: static const AFX_DATA CRuntimeClass classCObject;
//   这个就没有看懂了,这个类属性从CObject中派生过去有什么用,难道是用来记录最顶层的类的类型????????
//
///

#ifdef _AFXDLL
class CObject
#else
class AFX_NOVTABLE CObject
#endif
{
public:

// Object model (types, destruction, allocation)
 virtual CRuntimeClass* GetRuntimeClass() const; //这个const是不是指明这是个只有const CObject对象才能访问的函数??
 virtual ~CObject();  // virtual destructors are necessary,effective c++ sec-edit中条款14:确定基类有虚析构函数

 // 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:

 //哈哈,正好是拷贝构造函数和赋值操作赋,即是如果永远用不到这个,而且类中需要动态分配内存,那么定义自己的拷贝构造
 //函数并声明为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 AFX_DATA CRuntimeClass classCObject;
#ifdef _AFXDLL
 static CRuntimeClass* PASCAL _GetBaseClass();
#endif
};


/*-----------------------------------------------------------------------------------------
 *类名称: CCmdTarget
 *基  类: CObject
 *
 *注  意:
 *  1. 通过 virtual BOOL OnCmdMsg(UINT nID, int nCode, void* pExtra,AFX_CMDHANDLERINFO* pHandlerInfo);
 *   大致可以理解了,为什么说从CCmdTarget派生出来的,就能接收标准命令消息,
 *-----------------------------------------------------------------------------------------*/
#ifdef _AFXDLL
class CCmdTarget : public CObject
#else
class AFX_NOVTABLE CCmdTarget : public CObject
#endif
{
 DECLARE_DYNAMIC(CCmdTarget)  //RTTI
protected:

public:
// Constructors
 CCmdTarget();     //为什么没有定义析构函数,有的,有的,只是在后面,也因为要作基类,被声明为虚析构函数,
         //virtual ~CCmdTarget();

// Attributes
 LPDISPATCH GetIDispatch(BOOL bAddRef);
  // retrieve IDispatch part of CCmdTarget
 static CCmdTarget* PASCAL FromIDispatch(LPDISPATCH lpDispatch);
  // map LPDISPATCH back to CCmdTarget* (inverse of GetIDispatch)
 BOOL IsResultExpected();
  // returns TRUE if automation function should return a value

// Operations
 void EnableAutomation();
  // call in constructor to wire up IDispatch
 void EnableConnections();
  // call in constructor to wire up IConnectionPointContainer

 void BeginWaitCursor();
 void EndWaitCursor();
 void RestoreWaitCursor();       // call after messagebox

#ifndef _AFX_NO_OLE_SUPPORT
 // dispatch OLE verbs through the message map
 BOOL EnumOleVerbs(LPENUMOLEVERB* ppenumOleVerb);
 BOOL DoOleVerb(LONG iVerb, LPMSG lpMsg, HWND hWndParent, LPCRECT lpRect);
#endif

// Overridables
 // route and dispatch standard command message types
 //   (more sophisticated than OnCommand)
 virtual BOOL OnCmdMsg(UINT nID, int nCode, void* pExtra,
  AFX_CMDHANDLERINFO* pHandlerInfo);

#ifndef _AFX_NO_OLE_SUPPORT
 // called when last OLE reference is released
 virtual void OnFinalRelease();
#endif

#ifndef _AFX_NO_OLE_SUPPORT
 // called before dispatching to an automation handler function
 virtual BOOL IsInvokeAllowed(DISPID dispid);
#endif

#ifndef _AFX_NO_OLE_SUPPORT
 // support for OLE type libraries
 void EnableTypeLib();
 HRESULT GetTypeInfoOfGuid(LCID lcid, const GUID& guid,
  LPTYPEINFO* ppTypeInfo);
 virtual BOOL GetDispatchIID(IID* pIID);
 virtual UINT GetTypeInfoCount();
 virtual CTypeLibCache* GetTypeLibCache();
 virtual HRESULT GetTypeLib(LCID lcid, LPTYPELIB* ppTypeLib);
#endif

// Implementation
public:
 virtual ~CCmdTarget();
#ifdef _DEBUG
 virtual void Dump(CDumpContext& dc) const;
 virtual void AssertValid() const;
#endif
#ifndef _AFX_NO_OLE_SUPPORT
 void GetNotSupported();
 void SetNotSupported();
#endif

protected:
 friend class CView;

 CView* GetRoutingView();
 CFrameWnd* GetRoutingFrame();
 static CView* PASCAL GetRoutingView_();
 static CFrameWnd* PASCAL GetRoutingFrame_();
 DECLARE_MESSAGE_MAP()       // base class - no {{ }} macros

#ifndef _AFX_NO_DOCOBJECT_SUPPORT
 DECLARE_OLECMD_MAP()
 friend class COleCmdUI;
#endif

#ifndef _AFX_NO_OLE_SUPPORT
 DECLARE_DISPATCH_MAP()
 DECLARE_CONNECTION_MAP()
 DECLARE_INTERFACE_MAP()

#ifndef _AFX_NO_OCC_SUPPORT
 DECLARE_EVENTSINK_MAP()
#endif // !_AFX_NO_OCC_SUPPORT

 // OLE interface map implementation
public:
 // data used when CCmdTarget is made OLE aware
 long m_dwRef;
 LPUNKNOWN m_pOuterUnknown;  // external controlling unknown if != NULL
 DWORD m_xInnerUnknown;  // place-holder for inner controlling unknown

public:
 // advanced operations
 void EnableAggregation();       // call to enable aggregation
 void ExternalDisconnect();      // forcibly disconnect
 LPUNKNOWN GetControllingUnknown();
  // get controlling IUnknown for aggregate creation

 // these versions do not delegate to m_pOuterUnknown
 DWORD InternalQueryInterface(const void*, LPVOID* ppvObj);
 DWORD InternalAddRef();
 DWORD InternalRelease();
 // these versions delegate to m_pOuterUnknown
 DWORD ExternalQueryInterface(const void*, LPVOID* ppvObj);
 DWORD ExternalAddRef();
 DWORD ExternalRelease();

 // implementation helpers
 LPUNKNOWN GetInterface(const void*);
 LPUNKNOWN QueryAggregates(const void*);

 // advanced overrideables for implementation
 virtual BOOL OnCreateAggregates();
 virtual LPUNKNOWN GetInterfaceHook(const void*);

 // OLE automation implementation
protected:
 struct XDispatch
 {
  DWORD m_vtbl;   // place-holder for IDispatch vtable
#ifndef _AFX_NO_NESTED_DERIVATION
  size_t m_nOffset;
#endif
 } m_xDispatch;
 BOOL m_bResultExpected;

 // member variable-based properties
 void GetStandardProp(const AFX_DISPMAP_ENTRY* pEntry,
  VARIANT* pvarResult, UINT* puArgErr);
 SCODE SetStandardProp(const AFX_DISPMAP_ENTRY* pEntry,
  DISPPARAMS* pDispParams, UINT* puArgErr);

 // DISPID to dispatch map lookup
 static UINT PASCAL GetEntryCount(const AFX_DISPMAP* pDispMap);
 const AFX_DISPMAP_ENTRY* PASCAL GetDispEntry(LONG memid);
 static LONG PASCAL MemberIDFromName(const AFX_DISPMAP* pDispMap, LPCTSTR lpszName);

 // helpers for member function calling implementation
 static UINT PASCAL GetStackSize(const BYTE* pbParams, VARTYPE vtResult);
#ifdef _PPC_
 SCODE PushStackArgs(BYTE* pStack, const BYTE* pbParams,
  void* pResult, VARTYPE vtResult, DISPPARAMS* pDispParams,
  UINT* puArgErr, VARIANT* rgTempVars, UINT nSizeArgs);
#else
 SCODE PushStackArgs(BYTE* pStack, const BYTE* pbParams,
  void* pResult, VARTYPE vtResult, DISPPARAMS* pDispParams,
  UINT* puArgErr, VARIANT* rgTempVars);
#endif
 SCODE CallMemberFunc(const AFX_DISPMAP_ENTRY* pEntry, WORD wFlags,
  VARIANT* pvarResult, DISPPARAMS* pDispParams, UINT* puArgErr);

 friend class COleDispatchImpl;

#ifndef _AFX_NO_OCC_SUPPORT
public:
 // OLE event sink implementation
 BOOL OnEvent(UINT idCtrl, AFX_EVENT* pEvent,
  AFX_CMDHANDLERINFO* pHandlerInfo);
protected:
 const AFX_EVENTSINKMAP_ENTRY* PASCAL GetEventSinkEntry(UINT idCtrl,
  AFX_EVENT* pEvent);
#endif // !_AFX_NO_OCC_SUPPORT

 // OLE connection implementation
 struct XConnPtContainer
 {
  DWORD m_vtbl;   // place-holder for IConnectionPointContainer vtable
#ifndef _AFX_NO_NESTED_DERIVATION
  size_t m_nOffset;
#endif
 } m_xConnPtContainer;

#ifdef _AFXDLL
 AFX_MODULE_STATE* m_pModuleState;
 friend class CInnerUnknown;
 friend UINT APIENTRY _AfxThreadEntry(void* pParam);
#endif

 virtual BOOL GetExtraConnectionPoints(CPtrArray* pConnPoints);
 virtual LPCONNECTIONPOINT GetConnectionHook(const IID& iid);

 friend class COleConnPtContainer;

#endif //!_AFX_NO_OLE_SUPPORT
};


/*------------------------------------------------------------------------------------------------
 *类名称: CException
 *基  类: CObject
 *注  意:
 *
 *------------------------------------------------------------------------------------------------*/

#ifdef _AFXDLL
class CException : public CObject
#else
class AFX_NOVTABLE CException : public CObject
#endif
{
 // abstract class for dynamic type checking
 DECLARE_DYNAMIC(CException)

public:
// Constructors
 CException();   // sets m_bAutoDelete = TRUE
 CException(BOOL bAutoDelete);   // sets m_bAutoDelete = bAutoDelete

// Operations
 void Delete();  // use to delete exception in 'catch' block

 virtual BOOL GetErrorMessage(LPTSTR lpszError, UINT nMaxError,
  PUINT pnHelpContext = NULL);
 virtual int ReportError(UINT nType = MB_OK, UINT nMessageID = 0);

// Implementation (setting m_bAutoDelete to FALSE is advanced)
public:
 virtual ~CException();
 BOOL m_bAutoDelete;
#ifdef _DEBUG
 void PASCAL operator delete(void* pbData);
#if _MSC_VER >= 1200
 void PASCAL operator delete(void* pbData, LPCSTR lpszFileName, int nLine);
#endif
protected:
 BOOL m_bReadyForDelete;
#endif
};

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值