[英]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.