当C++多继承遇上类型转换

1 由来

客户用陈旧的VC++6.0进行项目开发,有一块功能需要我来实现。让一个早就习惯了VS2013的人去使用C++支持不太好的VC6去做开发实在是非常不爽,于是另辟蹊径,打算使用VC++2013开发编译出DLL,供VC6下调用即可。使用C++开发DLL的基本原则是减少暴露和接口简单化,最常用的方式就是使用纯虚类导出接口。另一种就是使用C++实现,但是导出时只导出C函数。处于使用的便利性考虑,采用了第一种方式。

2 原型与问题

基本的设计思路可以用如下代码描述。

#include <iostream>
#include <hash_map>
using namespace std;


class I1
{
public:
 virtual void vf1()
 {
  cout << "I'm I1:vf1()" << endl;
 }
};


class I2
{
public:
 virtual void vf2()
 {
  cout << "I'm I2:vf2()" << endl;
 }
};


class C : public I1, public I2
{
private:
 hash_map<string, string> m_cache;
};


I1* CreateC()
{
 return new C();
}


int main(int argc, char** argv)
{
 I1* pI1 = CreateC();
 pI1->vf1();


 I2* pI2 = (I2*)pI1;
 pI2->vf2();


 delete pI1;
 return 0;
}

采用基于接口的设计方法,对外只暴露接口类I1和I2,对于实际的实现类C则对外隐藏。客户在使用的时候,只需要调用CreateC()就可以产生C类型的对象,而不必知道C的实现细节。然后通过不同的接口调用不同方面的功能。看起来一切还可以,但实际运行却是有问题的,上述代码执行结果如下:

当C++多继承遇上类型转换

第二行的输出对应pI2->vf2(),显然结果是错误的,调用者的本意是调用I2::vf2(),实际却调用了I1::vf1()。随后我发现这个问题其实在论坛上也有人提出过,也有不少人给出了答案,但是感觉解释的不够明确和详细,所以决定亲自一探究竟。

相关推荐