从两个多态类继承
鉴于以下代码,
class T {
public:
virtual ~T () {}
virtual void foo () = 0;
};
class U {
public:
U() {}
~U() {}
void bar () { std::cout << "bar" << std::endl; }
};
class A : public U, public T {
public:
void foo () { std::cout << "foo" << std::endl; }
};
int main () {
A * a = new A;
std::vector<U*> u;
std::vector<T*> t;
u.push_back(a);
t.push_back(reinterpret_cast<T*>(u[0]));
u[0]->bar ();
t[0]->foo ();
delete a;
return 0;
}
我得到了我期望的输出
bar
foo
但是,如果我将 U
的定义更改为,
class U {
public:
U() {}
virtual ~U() {}
virtual void bar () { std::cout << "bar" << std::endl; }
};
我仍然可以正常编译并且没有警告/错误,但现在的输出是
bar
bar
关于虚拟声明的内容阻止我调用 foo
?
Given the following code
class T {
public:
virtual ~T () {}
virtual void foo () = 0;
};
class U {
public:
U() {}
~U() {}
void bar () { std::cout << "bar" << std::endl; }
};
class A : public U, public T {
public:
void foo () { std::cout << "foo" << std::endl; }
};
int main () {
A * a = new A;
std::vector<U*> u;
std::vector<T*> t;
u.push_back(a);
t.push_back(reinterpret_cast<T*>(u[0]));
u[0]->bar ();
t[0]->foo ();
delete a;
return 0;
}
I get the output I would expect
bar
foo
However, if I change the definition of U
to
class U {
public:
U() {}
virtual ~U() {}
virtual void bar () { std::cout << "bar" << std::endl; }
};
I still compile fine and without warnings/errors but the output is now
bar
bar
What is it about the virtual declaration that prevents me from calling into the foo
?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
首先,您的示例中没有虚拟基类。包含虚函数的类称为多态。 (C++ 中有“虚拟基类”之类的东西,但它与您的示例无关。)
其次,代码的行为不依赖于任何虚拟声明。您使用
reinterpret_cast
故意破坏了基指针的完整性。因此,代码的行为未定义。从一个基指针到另一个基指针的直接转换(这就是您在代码中尝试执行的操作)称为交叉转换。 C++ 中唯一可以执行交叉转换的转换是
dynamic_cast
。您可以在没有
dynamic_cast
的情况下执行间接交叉转换,但为此,您必须首先使用static_cast
将指针向下转换为派生类型 (A *
) code> 然后将其上转换为另一个基本指针类型Firstly, there are no virtual base classes in your example. Classes that contain virtual functions are called polymorphic. (There is such thing as "virtual base classes" in C++ but it has nothing to do with your example.)
Secondly, the behavior of your code does not depend on any virtual declarations. You have deliberately destroyed the integrity of the base pointer by using
reinterpret_cast
. For this reason the behavior of the code is undefined.A direct cast from one base pointer to another (which is what you are trying to do in your code) is called cross-cast. The only cast in C++ that can carry out a cross-cast is
dynamic_cast
.You can perform an indirect cross-cast without
dynamic_cast
, but for that you have to downcast the pointer to the derived type first (A *
) usingstatic_cast
and then upconvert it to another base pointer type如果您使用
reinterpret_cast
,您将失去所有保证,并且您所做的任何事情都是“未定义的行为”。在这种情况下,我预计 VMT 会被搞乱,或者 VPTR 会被覆盖。举例来说,当我编译上面的第一个代码时,我的编译器执行时出现段错误。
如果你真的想“交叉执行”,你应该从一个公共基类派生,并通过 U 和 T 虚拟继承该基类(
:virtual public
),或者使用dynamic_cast
而不是reinterpret_cast
。If you use
reinterpret_cast
you loose all guarantees, and anything you do is "undefined behaviour". In this case, I expect the VMT got messed up, or the VPTR overwritten.As an illustration, when I compile the first code above, I get a segfault on execution on my compiler.
If you really want to "cross-execute" you should derive from a common base class, and inherit that base class by U and T virtually (
: virtual public
), or usedynamic_cast
instead ofreinterpret_cast
.像
u
一样填充t
:您不需要
reinterpret_cast
,因为A
是T
。Populate
t
just like you didu
:You don't need
reinterpret_cast
becauseA
is aT
.