微软从Visual Studio.NET 2002开始,引入了一种新的关键字:__interface,它是一种针对C++编译器的微软扩展,在相应文档中,对一个Visual C++接口进行了如下说明:
² 能从零个或多个基接口继承。
² 不能继承自一个基类。
² 只能包含公有及纯虚方法。
² 不能包含构造函数、析构函数、操作符函数。
² 不能包含静态方法。
² 不能包含数据成员;但允许有属性。
文档还注明:“一个C++类或结构可用以上规则来实现,但必须加上__interface。”因此,如果不在意可移植性的话,是否可用__interface这个扩展让编译器来完成剩下的工作呢?错了。
还记得虚拟析构函数吗?__interface并不会为实现一个类而添加虚拟析构函数,如果你仔细看过文档,就会发现它们实际上是由COM接口实现的,所以你从不会用到delete,因为它们是引用计数的对象,当计数为零时,会对自身调用delete。
那么在DeclareInterface 宏定义中使用__interface,这不就两全其美了吗?再看一下前面的规则:“不能包含构造函数、析构函数及操作符函数”。这可能让人觉得有点不可能,甚至会想到为什么要在COM接口中使用__interface呢,况且也不适合这里所说到的通用接口啊。那么,请再往下看。
两全其美的方法
这儿有一个非常简单的解决方案:接口的名字实际上用于声明一个类,而这个类包含了一个虚拟析构函数且继承自包含了必要方法的一个__interface。现在宏定义如下:
使用上面定义的宏来声明一个接口:// // CppInterfaces2.h // #define Interface class #define implements public #define DeclareInterface(name) __interface actual_##name { #define DeclareBasedInterface(name, base) __interface actual_##name \ : public actual_##base { #define EndInterface(name) }; \ Interface name : public actual_##name { \ public: \ virtual ~name() {} \ };
也许你已注意到了,新的宏定义用到了两次接口名(IBar),第一次是DeclareInterface(),而第二次是EndInterface()。另一方面,倘若你不怎么在意移植性问题,那么这个宏比微软编译器所提供的扩展有利得多,因为接口(仅指提供了实现类的纯虚方法、虚拟析构函数且没有数据成员的接口)的方方面面,都自动完成了,甚至不必显式声明接口方法为virtual或纯虚(=0)——虽然声明了也没什么关系。// // IBar2.h // DeclareInterface(IBar) int GetBarData() const; void SetBarData(int nData); EndInterface(IBar)