不向上转换为真正的基础 class

Upcasting not to real base class

我有点被糟糕的 class 层次结构所困扰。

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 的指针(引用)转换为指向 class A 的指针(引用)

我知道最好的解决方案是让 class C 继承自 A,但它仍然会导致 class a1(两个基数 A)出现一些问题。

The question: is it possible convert a pointer(reference) to C into pointer(reference) to class A.

除非 类 是多态的,即至少有一个虚拟成员函数。在这种情况下,dynamic_cast 可用于侧投,如 StoryTeller 的回答所示。

但是,如果 C 指针(引用)指向继承 A 的子指针,那么您可以先向下转换为该子指针,然后再转换为 A

c1 c;
C& cref = c;
A& aref = static_cast<c1&>(cref);

这当然不一定是理想的,因为您不能只转换具体类型未知的任意 C 指针。

I understand that best solution is to make just class C inherited from A

如果您这样做,那么所有 C 指针都可以隐式转换为 A 指针。

but still it can cause some problems with class a1 (two base 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;
}

您正在尝试做的事情叫做 "side-cast"。内置的 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;
}

但我认为您需要重新设计 类 的观点是非常有道理的。应该不需要做旁白。

上面的两个答案都是正确的,但我认为第一个答案得到了更广泛的解释。 我可能会使用的另一个解决方案是创建一个奇怪的访问者,例如:

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;