c++: 模板 class 和通用 class 的多重继承是否有效?

c++: Is a multiple inheritance from template class and general class valid?

我想弄清楚为什么 b->boo() 实际上会调用 a.far()。
是否禁止从模板 class 和通用 class 进行多重继承?为什么继承顺序很重要? 代码在这里:

#include <iostream>

template <int somecount>
class inner_parent_class
{
public:
    int array[somecount];
    virtual void far() = 0;
};

class any_class
{
public:
    virtual void boo() = 0;
};

template <int somecount>
class child_class_bad : public inner_parent_class<somecount>, public any_class
{
public:
    virtual void boo() override
    {
        std::cout << "call me" << std::endl;
    }

    virtual void far() override
    {
        std::cout << "do not call me" << std::endl;
    }
};

template <int somecount>
class child_class_good : public any_class, public inner_parent_class<somecount>
{
public:
    virtual void boo() override
    {
        std::cout << "call me" << std::endl;
    }

    virtual void far() override
    {
        std::cout << "do not call me" << std::endl;
    }
};

int main()
{
    {
        child_class_good<32> a;
        any_class* b;
        auto c = dynamic_cast<void*>(&a);
        b = reinterpret_cast<any_class*>(c);
        b->boo();
    }
    {
        child_class_bad<32> a;
        any_class* b;
        auto c = dynamic_cast<void*>(&a);
        b = reinterpret_cast<any_class*>(c);
        b->boo();
    }

    return 0;
}

@ GCC 9.3.0

@ VS 2019 16.5.3

我想 child classes(child_class_good 和 child_class_bad)是不同的 classes 即使他们的 class 名字是相同的,因为它们是模板 classes 并且在编译时单独构建。然而,每个 class 可能有自己的 v-table,所以我认为调用 boo() 作为它们的公共 parent class any_class 应该正确工作。

reinterpret_cast 不能用于执行您想要执行的操作。从 void*T*reinterpret_cast 只产生一个指向有效 T* 的指针,如果给它的 void* 指针是指向对象的指针输入 T.

做一个 dynamic_cast<void*>(p) returns 一个 void* 指向由 p 指向的最派生对象。由于您的 &a 实际上是它指向的最派生对象,因此它只是将指针转换为 void*.

然后你在 void* 上执行 reinterpret_cast<any_class*>void* 指向 child_class_good<32>child_class_bad<32> 类型的对象。您的演员表示指针实际上指向 any_class。这是不正确的(两种类型都不是标准布局,因此未定义基本 类 的布局),因此尝试使用结果将产生未定义的行为。

您标识为good的情况与bad一样无效;它只是碰巧起作用。

不清楚你为什么要尝试做你想做的任何事情,但是没有有效的方法来获取指向未知类型的最派生对象的 void*并将其投射到任何有用的东西上。为了使用 void*,您 必须 知道用于生成 void*.

的确切类型