摘要:程序员在我看来是比较会偷懒的一个群体。为了在开发软件的时候减少人工操作,他们会使用各种各样的软件和语言特性,例如IDE和预处理宏。李建忠在他的BLOG(http://blog.joycode.com/lijianzhong/archive/2005/05/08/50440.aspx)中提到,为了简化声明属性的工作,他的同事自己写了一些小工具来生成需要的代码。在C++托管扩展中,这个工作稍微简单一些,用预处理宏就可以了。
#define DECLARE_PROPERTY_DOUBLE_PUBLIC(propertyName)\protected:\ double _##propertyName;public:\ __property double get_##propertyName(){ return _##propertyName; }\ __property void set_##propertyName( double new_##propertyName ){ _##propertyName= new_##propertyName; }
public __gc __sealed class Vector {public: // ... DECLARE_PROPERTY_DOUBLE(x) DECLARE_PROPERTY_DOUBLE(y) DECLARE_PROPERTY_DOUBLE(z)
};
当然,如果使用C++/CLI的话,这个工作更加简单:
public ref class Vector sealed{ public: property double x; property double y; property double z;};
我在编程的时候也是个彻底的实用主义者,需要大量重复编写的代码都是尽量用宏实现。例如,我用如下的宏来简化CCmdTarget派生类对IOleCommandTarget类的处理:
#define DECLARE_IOLECOMMANDTARGET\ STDMETHOD(QueryStatus)(const GUID* pguidCmdGroup, ULONG cCmds, OLECMD prgCmds [],OLECMDTEXT* pcmdtext);\ STDMETHOD(Exec)(const GUID*,DWORD nCmdID, DWORD nCmdExecOpt,VARIANTARG* pvarargIn, VARIANTARG* pvarargOut);
#define IMPLEMENT_IOLECOMMANDTARGET(theClass,localclass)\STDMETHODIMP theClass::X##localclass::Exec(const GUID* pguidCmdGroup,DWORD nCmdID, DWORD nCmdExecOpt,VARIANTARG* pvarargIn, VARIANTARG* pvarargOut)\{\ METHOD_PROLOGUE_EX(theClass, localclass)\ ASSERT_VALID(pThis);\ return pThis->Exec(pguidCmdGroup,nCmdID,nCmdExecOpt,pvarargIn,pvarargOut);\}\STDMETHODIMP theClass::X##localclass::QueryStatus(const GUID* pguidCmdGroup, ULONG cCmds, OLECMD prgCmds[],OLECMDTEXT* pcmdtext)\{\ METHOD_PROLOGUE_EX(theClass, localclass)\ ASSERT_VALID(pThis);\ return pThis->QueryStatus(pguidCmdGroup,cCmds,prgCmds,pcmdtext);\}
#define IMPLEMENT_LOCALCLASS_UNKNOWN(theClass,localclass) \STDMETHODIMP_(ULONG) \theClass::X##localclass::AddRef() \{ \ METHOD_PROLOGUE_EX(theClass, localclass) \ ASSERT_VALID(pThis); \ return pThis->ExternalAddRef(); \} \\STDMETHODIMP_(ULONG) \theClass::X##localclass::Release() \{ \ METHOD_PROLOGUE_EX(theClass, localclass) \ ASSERT_VALID(pThis); \ return pThis->ExternalRelease(); \} \STDMETHODIMP theClass::X##localclass::QueryInterface( \REFIID iid, LPVOID* ppvObj) \{ \ METHOD_PROLOGUE_EX(theClass, localclass) \ ASSERT_VALID(pThis); \ return pThis->ExternalQueryInterface(&iid, ppvObj); \}
这样要在CCmdTarget派生类中实现IOleCommandTarget接口的话,只需要编写实现函数就行了:
//声明class CScreenCaptureGDI : public CScreenCaptureBase{ DECLARE_OLECOMMANDTARGET…… DECLARE_INTERFACE_MAP() BEGIN_INTERFACE_PART(OleCommandTarget, IOleCommandTarget) DECLARE_OLECOMMANDTARGET ......[
阅读全文]