是否可以将dynamic_cast从一个基类转换为另一个基类?

发布于 2024-09-25 09:36:21 字数 466 浏览 8 评论 0原文

例如,我有这样的代码

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,所以 WonderFULL 永远不会执行。是否有可能执行这样的转换?

For instance I have code like that

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();
}

However wonderFULL is never executed due to impossibility to cast ptr to b1. Is it possible at all to perform such a conversion?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

夜无邪 2024-10-02 09:36:22

#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。我的结论是,您没有显示重现问题所需的代码。

获取实际代码(的副本),并通过逐步删除不必要的代码来提炼它,直到派生出一个独立的(除了标准库之外不需要其他标头)可重现问题的可编译示例。这样做的时候你很可能会发现问题。但是,如果您不这样做,您可以回到这里询问完美的重现案例。

This

#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;
}

prints wonderful for me. My conclusion is that you're not showing the code necessary for your problem to reproduce.

Take (a copy of) your actual code and by removing uneccessary code step by step distill it until you derive at a self-contained (needs no other headers except from the std lib), compilable example that reproduces the problem. Very likely you will find the problem while doing so. However, if you don't, you have the perfect repro case to come back here and ask about.

深海少女心 2024-10-02 09:36:22

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

如果你让它看起来像:

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

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

然后一切工作

You have some syntax errors, but your real problem is dynamic_cast won't work properly if your base classes don't have at least one virtual function.

If you make it look like:

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

And then fix your other errors:
wonderFULL is private, and never defined.
magicFunction is declared after it is used.

Then everything works.

喵星人汪星人 2024-10-02 09:36:22

您可以向上转换层次结构然后再向下转换:

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 */ }
}

You can cast up the hierarchy then back down:

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 */ }
}
柒夜笙歌凉 2024-10-02 09:36:22

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

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

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

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

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

Going by what I understand of the way some C++ compilers arrange the class hierarchy in memory it should be possible to cast from one base class to another, but you have to first cast to the derived class.

Therefore you would need to do something like:

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

This casts the given pointer ptr to the derived class, and then it gets implicitly cast to its other base class pointer.

However another easier way to do this would be to just have a method in the Base2 class that returns a Base1 pointer, and the derived class can implement this itself without any tricky code. (The same function in Base2 can just return NULL if you don't want a pure virtual class).

风为裳 2024-10-02 09:36:22

我已经找到问题了。这与dynamic_casts无关。我正在检查错误的对象,该对象不是从抽象基继承的。谢谢。

I've found the problem. It was not about dynamic_casts. I was checking wrong object which was not inherited from abstract base. Thanks.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文