打开APP
userphoto
未登录

开通VIP,畅享免费电子书等14项超值服

开通VIP
C++ 多重继承的强制类型转换。


class A
{
public:
     A() { m_data = 'A';}
    ~A() {}
    char m_data;
};

class B
{
public:
     B() { m_data = 'B';}
    ~B() {}
    char m_data;
};

class C : public A, public B
{
public:
     C() { m_data = 'C';}
    ~C() {}
    char m_data;
};

class D : public C
{
public:
     D() { m_data = 'D';}
    ~D() {}

    void test()
    {
        DWORD value = (DWORD)this;

        A* address1 = (A*)(value);// 编译通过,类型转换错误(仅在在虚拟继承的情况下),正确的写法:A* address1 = (A*)((D*)value);
        B* address2 = (B*)(value);// 编译通过,类型转换错误,正确的写法:B* address2 = (B*)((D*)value);
        C* address3 = (C*)(value);
        D* address4 = (D*)(value);

        printf("%c %c %c %c", address1->m_data, address2->m_data, address3->m_data, address4->m_data);
    }

    char m_data;
};

void main()
{
  D d;
  d.test();
}

代码运行后,结果为A A C D,显然B这个类没有正确转换。

A和B都是D的父类,为什么A* address1 = (A*)value这句转换正确,而B* address2 = (B*)(value)出错呢?这就是多重继承的不可判断性。

正因为这种特性的存在,我们在实际使用中,应该尽量避免多重继承,选择单一继承这种模式。JAVA就是如此,最初设计时就只能单一继承,而多重继承则演变为纯虚接口(interface),这样就规避了此类问题。但可惜,在C++里,WTL和QT都大量使用这种模型,想在实际项目中完全避免,也很困难。

要解决,有几种方法。

1. 把B* address2 = (B*)(value)这行,改写为B* address2 = (B*)((D*)value); 这样就能直观的传达给编译器,B正确的偏移量。

最终输出A B C D,正是我们想要的结果。

2. 显示使用static_cast,当编译器不能确定转换类型时,会提示编译错误信息。

例如:
B* address2 = static_cast<B*>(value); // 编译失败。
B* adddres2 = static_cast<B*>((D*)value); // 编译成功,并且结果正确。

3. 使用RTTI解决。


--------------------------------------------------
本站仅提供存储服务,所有内容均由用户发布,如发现有害或侵权内容,请点击举报
打开APP,阅读全文并永久保存 查看更多类似文章
猜你喜欢
类似文章
虚继承和多重继承
什么情况下指针类型转换会改变指针的值(转)
学习Java的笔记(3)
接口和抽象类的区别和作用
Java 接口 | 菜鸟教程
c++对象内存结构
更多类似文章 >>
生活服务
热点新闻
分享 收藏 导长图 关注 下载文章
绑定账号成功
后续可登录账号畅享VIP特权!
如果VIP功能使用有故障,
可点击这里联系客服!

联系客服