我有点担心这种糟糕的类层次结构的可怕问题。
class A {...}; // abstract
class B : public A {...}; // abstract
class C {...}; // abstract
class a1 : public B, public C {...}; // indirect inheritance of A
class c1 : public A, public C {...};
问题:是否可以将指针(引用)转换为C指针(引用)转换为A类。
据我所知,最好的解决办法是让C语言继承自A,但它仍会导致类a1(两个基础A)出现问题。
答案 0 :(得分:3)
问题:是否可以将指针(引用)转换为C指针(引用)转换为A类。
除非类是多态的,即具有至少一个虚拟成员函数。在那种情况下,dynamic_cast可以用于侧面演员,如StoryTeller的回答所示。
但是,如果C
指针(引用)指向继承A
的子项,则可以先转换为该子指针,然后转到A
。
c1 c;
C& cref = c;
A& aref = static_cast<c1&>(cref);
这当然不一定是理想的,因为你不能只转换任何具体类型未知的任意C
指针。
我知道最好的解决方案是让C级继承自A
如果你这样做了,那么所有C
指针都可以隐式转换为A
指针。
但是它仍然会导致类a1(两个基数A)出现问题。
要解决这些问题,你需要共享基础,即虚拟继承。
struct A {}; // abstract
struct B : virtual A {}; // abstract
struct C : virtual A {}; // abstract
struct a1 : B, C {}; // indirect inheritance of A
struct c1 : C {};
int main() {
c1 c;
C& cref = c;
A& aref = cref;
}
答案 1 :(得分:3)
你要做的事情被称为“侧面演员”。内置的dynamic_cast
表达式可以做到这一点。但它并不便宜,你最好不要在你的项目中关闭对RTTI的支持(你已经提到你的类是抽象的,因此需要虚函数,其中RTTI的生成需要声明)。
请参阅 Live
#include <cassert>
struct A {
virtual ~A() = default;
};
struct B : public A {
virtual ~B() = default;
};
struct C {
virtual ~C() = default;
};
struct a1 : public B, public C {
a1() = default;
virtual ~a1() = default;
}; // indirect inheritance of A
int main() {
a1 a;
C* c = &a;
assert(dynamic_cast<A*>(c) != nullptr);
return 0;
}
但我认为你对需要重新设计课程的看法是非常有道理的。不应该出现侧面演员的需要。
答案 2 :(得分:0)
上述两个答案都是正确的,但我认为第一个答案更为广泛。 我可能会使用的另一个解决方案是创建一个奇怪的访问者,例如:
PointerCreator
{
void visit ( const a1 & _a )
{
m_pointerToA = &_a;
}
void visit ( const c1 & _c )
{
m_pointerToA = &_a;
}
A * m_pointerToA;
};
PointerCreator pC;
a1.accept( pC );
A& = *pC.m_pointerToA;