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*
.
的确切类型
我想弄清楚为什么 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*
.