是否可以从一个基类到另一个基类进行dynamic_cast?

时间:2010-09-28 13:50:42

标签: c++ class inheritance dynamic-cast

例如,我有类似的代码

class Base1
{
  virtual void wonderFULL() = 0;
};

class Base2
{
  // all this weird members
};

class Derived : public Base1, public Base2
{
  // not so weird members
};

int main()
{
  Derived Wonder;
  magicFunction(&Wonder);
  return 0;
}

void magicFunction(Base2 *ptr)
{
  if (Base1 *b1 = dynamic_cast<Base1 *>(ptr))
    b1->wonderFULL();
}

然而,由于不可能将ptr转换为b1,所以neverFULL永远不会被执行。是否有可能进行这样的转换?

5 个答案:

答案 0 :(得分:7)

这个

#include <iostream>

class Base1 {
public:
    virtual void wonderFULL() = 0;
};

class Base2 {
public:
    virtual ~Base2() {}                                       // added so the code compiles
};

class Derived : public Base1, public Base2 {
    virtual void wonderFULL() {std::cout << "wonderful\n";}   // added so the code compiles
};

void magicFunction(Base2 *ptr) {
    if (Base1 *b1 = dynamic_cast<Base1 *>(ptr))
        b1->wonderFULL();
}

int main() {
    Derived Wonder;
    magicFunction(&Wonder);
    return 0;
}

为我打印wonderful。我的结论是,您没有显示重现问题所需的代码。

获取(副本)您的实际代码,并逐步删除不必要的代码,直到您获得自包含(除了std lib之外不需要其他标题),再现问题的可编译示例。这样做很可能会发现问题。但是,如果你不这样做,你就有了完美的复制案例,可以回到这里询问一下。

答案 1 :(得分:2)

您可以将层次结构强制转换为

void magicFunction(Base2& ptr)
{
    try
    {
        Derived&  d = dynamic_cast<Derived&>(ptr);
        Base1&    b = dynamic_cast<Base1&>(d);
        b.wonderFULL();
    }
    catch(const std::bad_cast&)
    { /* Cast failed */ }
}

答案 2 :(得分:2)

您有一些语法错误,但如果您的基类没有至少一个虚函数,那么您的真正问题是dynamic_cast将无法正常工作。

如果你看起来像:

class Base2
{
public:
  virtual ~Base2() {}
  // all this weird members
};

然后修复您的其他错误:   wonderFULL是私有的,从未定义过。   magicFunction在使用后声明。

然后一切works

答案 3 :(得分:0)

按照我对一些C ++编译器在内存中排列类层次结构的理解,应该可以从一个基类转换到另一个基类,但是你必须首先转换为派生类。

因此,您需要执行以下操作:

Base1* b1 = dynamic_cast<Derived*>(ptr);

这会将给定指针ptr强制转换为派生类,然后将其隐式强制转换为其他基类指针。

然而,另一种更简单的方法是在Base2类中只有一个返回Base1指针的方法,派生类本身可以实现它,而不需要任何棘手的代码。 (如果您不想要纯虚拟类,Base2中的相同函数只能返回NULL。)

答案 4 :(得分:0)

我发现了问题。这不是关于dynamic_casts。我正在检查错误的对象,它不是从抽象基础继承的。感谢。