转换为多重继承

Posted

技术标签:

【中文标题】转换为多重继承【英文标题】:Cast to multiple inheritance 【发布时间】:2013-12-03 04:04:26 【问题描述】:

我想知道是否可以在不知道其初始类型的情况下将一个对象转换为它继承自的多个类。例如,假设我有以下结构:

struct A 
    int a;
;

struct B 
    int b;
;

struct C 
    int c;
;

struct D 
    int d;
;

struct Z : A, B, C, D ;

然后我将 Z 的实例添加到向量中。

vector<A *> v;
Z *zed = new Z();
v.push_back(zed);

现在假设我知道向量中的第一个元素继承自 A 和 B,我想将其强制转换为 A 和 B。

struct Tmp : A, B ;
Tmp *tmp = static_cast<Tmp *>(v[0]);
tmp->b = 6;
cout << zed->b << endl;

但是,这样做会导致问题。主要是如果 Z 被定义为 struct Z : A, C, D, B ;,那么 cout &lt;&lt; zed-&gt;b &lt;&lt; endl; 将打印 0 而不是 6。您将如何解决这个问题?

我知道这样做可能是不安全的,并且可能是糟糕的设计,但是,我仍然有兴趣知道它是否可能。

【问题讨论】:

你可以做到,但前提是你引入了一个层次结构。 IE。引入一个struct AB : A, BZTmp 都继承自。但正如你所建议的,这真是糟糕的设计。 【参考方案1】:

您可以使用dynamic_cast 来“跨越”继承层次结构。但是“from”类型中至少需要有一个虚函数,并且不能从虚或多重继承的基类进行强制转换。

struct A 
    int a;
    virtual ~A() 
;

struct Z : A, B, C, D ;
vector<A *> v;
Z *zed = new Z();
v.push_back(zed);

B *tmp = dynamic_cast<B *>(v[0]);

这使用运行时类型检查,如果 v[0] 毕竟不是从 B 派生的,则生成 nullptr

至于struct Tmp,尽管有共同的基础,但根据语言,它与Z 完全无关。如果Tmp 也声明了自己的成员怎么办?如果您想访问 BC 子对象而不管它们是如何继承的,请使用两个单独的 dynamic_cast 操作获取引用。

【讨论】:

【参考方案2】:

您似乎在那里不止一次使用AB(既要转换又要创建Tmp 结构。我建议您给struct X : A, B ... 起一个有用的名称并定义@987654325 @as:struct Z : X, C, D .

然后演员变成:

X* tmp = static_cast<X*>(v[0]);
tmp->b = 6;
std::cout << zed->b << std::endl;

【讨论】:

以上是关于转换为多重继承的主要内容,如果未能解决你的问题,请参考以下文章

c++ 多重继承强制转换

C++多重继承与void*指针转换问题

虚拟多重继承和强制转换

为啥我不能在多重继承期间动态转换“sideways”?

多重继承下的类型转换

多重继承下的类型转换