C++中没有借口的概念,只有抽象父类.
不过借口也不过是全部抽象的类,用抽象类实现也是一样的.
这种东西,主要是思想,
作为一种比类更强大的语言特性,已出现在了Java、C#及其他语言中,但C++中却没有。本文中将要演示的,是一种C++接口概念“方法学”上的实现;且从Visual Studio.NET 2002开始,微软也以一种扩展的方法来走这同一条路,其允许编译器来实现接口中的大多数特性,当然了,C++托管扩展也支持 .NET接口的定义与实现。不管怎样,在这些实现机制之间,还是有一些微妙差别的,都需要你给予充分的重视。
一个接口在没有特定实现之前,其描述了类的行为或功能,代表了提供者与使用者都必须遵守的约定,它定义各个实现者的所需完成的功能,而不管它们怎样具体去做。
第一个版本
首先,在头文件中定义了一些宏,你可在程序的预编译头文件中包含它:
//
// CppInterfaces.h
//
#define Interface class
#define DeclareInterface(name) Interface name { \
public: \
virtual ~name() {}
#define DeclareBasedInterface(name, base) class name :
public base { \
public: \
virtual ~name() {}
#define EndInterface };
#define implements public
使用这些宏,能以下面这种方式声明一个接口:
//
// IBar.h
//
DeclareInterface(IBar)
virtual int GetBarData() const = 0;
virtual void SetBarData(int nData) = 0;
EndInterface
接下来,可像下面这样声明一个实现了这个接口的类:
//
// Foo.h
//
#include "BasicFoo.h"
#include "IBar.h"
class Foo : public BasicFoo, implements IBar
{
//构造及析构函数
public:
Foo(int x) : BasicFoo(x)
{
}
~Foo();
现在就能在C++中使用接口了,但是,因为它们不是直接被语言支持的,所以要遵循以下这些在编译时不能自动应用的规则,毕竟,在所有编译器的“眼中”,这些都是多重继承和抽象基类。
�0�5 当声明一个类时,要使用基类来搭建“结构性”的继承(成为“is a 是一个”的关系),例如:CFrameWnd继承自CWnd,CBitmapButton继承自CButton,xxDialog继承自CDialog。尤其当在使用MFC时,这点非常重要,以避免破坏MFC的运行时类机制。
�0�5 为实现接口使用额外的基类,有多少个接口,就用多少个基类。例如:lass Foo : public BasicFoo, implements IBar, implements IOther, implements IWhatever
�0�5 不要在接口中声明任何变量。接口是用来表示行为,而不是数据,除此以外,这样做还可以在使用多重继承并继承自同一个接口不止一次时,避免某些错误。
�0�5 在接口中把所有的成员函数声明为纯虚函数(即带上“=0”)。这可确保声明实现接口的每个实例化的类都实现其自已的函数;也可在抽象类中部分实现一个接口,只要在继承来的类中实现了余下的函数。另外,接口不提供“基本”实现,因为必须保证每个得到接口指针的调用者,都可以调用它的任意成员;把所有的接口成员声明为纯虚,可在编译期间强制应用这条规则。
�0�5 接口只能从接口继承,而从其他任何类型继承都不行,可使用DeclareBasedInterface()来达到此目的。正常的类能选择实现基接口或继承来的接口,而后者也意味着实现了前两者。
把一个实现了某些接口的类的指针,赋值给这些接口的指针,并不需要进行转换,因为实际上是在把它转换为一个基类;但反过来,把一个接口指针,赋给一个实现它的类的指针,就需要显式转换了,因为是在把它转换为一个继承类。由于我们实际上是在使用多重继承——也可把它看作单重继承加上接口实现,且它们可能需要不同的内存值