(《COM本质论》中的例子)
采用抽象类作为二进制接口。
class IFastString
{
public:
virtual int Length(void) const = 0;
virtual int Find(const char *psz) const = 0;
};
实现类从接口继承。
class FastString :public IFastString
{
public:
FastString(const char *psz);
~FastString(void);
int Length(void) const;
int Find(const char *psz) const;
private:
const int m_cch;
char *m_psz;
};
FastString::FastString(const char *psz)
:m_cch(strlen(psz)),m_psz(new char[m_cch + 1])
{
strcpy(m_psz,psz);
}
FastString::~FastString(void)
{
delete []m_psz;
}
int FastString::Length(void) const
{
return m_cch;
}
int FastString::Find(const char *psz) const
{
return 0;
}
这样也还是必须包含实现类,因为抽象类必须靠实现类来实例化,解决方法是提供一个全局函数来实例化实现类,从而隐藏实现类。
extern "C" IFastString *CreateFastString(const char *psz);用CreateFastString代替new FastString。
析构函数不是虚函数,因此不能动态的识别调用哪个析构函数,会造成内存泄漏,如果改为虚函数,则破坏了接口类的编译器独立性,因为虚析构函数在vtbl中的位置随编译器的不同而不同。显示的增加一个Delete方法,作为接口类的另一个纯虚函数。
class IFastString
{
public:
virtual void Delete(void) = 0;
virtual int Length(void) const = 0;
virtual int Find(const char *psz) const = 0;
};
void FastString::Delete()
{
delete this;
}
在动态库中,除了CreateFastString函数以外,其他的成员函数都是虚函数,通过vtbl的函数指针间接调用,因此不需要导出符号,不受“不同编译器篡改符号名称”的影响。