[英]Multiple inheritance of virtual classes
假设我有以下代码:
class a {
public:
virtual void do_a() = 0;
}
class b {
public:
virtual void do_b() = 0;
}
class c: public a, public b {
public:
virtual void do_a() {};
virtual void do_b() {};
}
a *foo = new c();
b *bar = new c();
foo->do_a()
和bar->do_b()
工作? 这里的内存布局是什么?
a-> do_a()和b-> do_b()是否可以工作?
假设您的意思是foo->do_a()
和bar->do_b()
,因为a
和b
不是object ,它们的类型为 yes。 他们会工作的。 你试过那样吗?
这里的内存布局是什么?
那主要是实现定义的。 幸运的是,除非您想编写不可移植的代码,否则您无需了解这一点。
他们为什么不呢? 内存布局通常如下所示:
+----------+
| A part |
+----------+
| B part |
+----------+
| C part |
+----------+
如果将foo
和bar
转换为void*
并显示它们,则会获得不同的地址,但是编译器知道这一点,并且会在调用函数时安排this
指针正确固定。
正如其他人所提到的,以下内容将毫无问题地起作用
foo->do_a();
bar->do_b();
但是,这些将无法编译
bar->do_a();
foo->do_b();
由于bar
是b*
类型,因此不知道do_a
。 foo
和do_b
也是如此。 如果要进行这些函数调用,则必须向下转换。
static_cast<c *>(foo)->do_b();
static_cast<c *>(bar)->do_a();
示例代码中未显示的另一个非常重要的事情是,在继承并通过基类指针引用派生类时,基类必须具有一个虚拟析构函数 。 如果不是,则以下内容将产生未定义的行为。
a* foo = new c();
delete a;
解决方法很简单
class a {
public:
virtual void do_a() = 0;
virtual ~a() {}
};
当然,也需要对b
进行此更改。
foo->do_a(); // will work
bar->do_b(); // will work
bar->do_a(); // compile error (do_a() is not a member of B)
foo->do_b(); // compile error (do_b() is not a member of A)
// If you really know the types are correct:
C* c = static_cast<C*>(foo);
c->do_a(); // will work
c->do_b(); // will work
// If you don't know the types, you can try at runtime:
if(C* c = dynamic_cast<C*>(foo))
{
c->do_a(); // will work
c->do_b(); // will work
}
是的,当然可以。 机械学有点棘手。 该对象将具有两个vtable,一个用于父类的vtable,另一个用于父类b的vtable。 指针将被调整,使其指向与指针类型相对应的对象子集,从而导致以下令人惊讶的结果:
c * baz = new c;
a * foo = baz;
b * bar = baz;
assert((void *)foo == (void *)bar); // assertion fails!
编译器在分配时就知道类型,并且确切地知道如何调整指针。
当然,这完全取决于编译器。 C ++标准中没有任何内容表明它必须以这种方式工作。 只是它必须起作用。
a-> do_a()和b-> do_b()是否可以工作?
没有。
foo->do_a()
和bar->do_b()
工作?
是。 您的代码是虚拟函数分派的典型示例。
你为什么不试试呢?
这里的内存布局是什么?
谁在乎?
(即,这是实现定义的,从您那里抽象出来的。您既不需要也不想知道。)
他们会工作的。 就内存而言,这取决于实现。 您已经在堆上创建了对象,并且对于大多数系统而言,值得注意的是堆上的对象向上增长(如果堆栈向下增长)。 因此, 可能会有:
Memory:
+foo+
-----
+bar+
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.