![](/img/trans.png)
[英]C++ Derived polymorphic class - does it contain an entire instance of Base, including a vptr?
[英]c++ base class contain instance of a derived class
我想知道是否有人可以向我解釋我如何能夠實現類似的東西:
namespace advanced_cpp_oop
{
class A
{
B b;
};
class B : public A
{
};
}
int main()
{
}
基類的實例在哪里可以包含派生類的實例? 編譯上述代碼時,會產生以下錯誤:
g++ advanced_cpp_oop.cpp
advanced_cpp_oop.cpp:8:5: error: ‘B’ does not name a type
編譯的(幾乎)等效的Java代碼是:
public class AdvancedCppOop
{
public static void main(String[] args)
{
A a;
}
}
class A
{
B b;
}
class B extends A
{
}
謝謝
您需要添加一個指針和一個前向聲明:
namespace advanced_cpp_oop
{
class B;
class A
{
B* b;
};
class B : public A
{
};
}
在您的 C++ 代碼中,您正在class A
中創建class B
的實例,這是不可能的,因為編譯器尚不知道class B
任何內容(尤其是不知道大小)。
使用我的答案中的代碼,您需要動態分配class B
的實例並將其分配給代碼中其他位置的b
指針。
附帶說明一下,從設計的角度來看,這實際上沒有意義,因為父類不應該依賴於子類。
您必須使用某種類型的指針(例如 unique_ptr)和前向聲明來執行此操作:
class B;
class A
{
std::unique_ptr<B> b;
};
class B : public A
{
};
不過這很愚蠢,您可能應該重新考慮您的設計。
C++ 和 Java 之間有一個非常重要的區別。 C++是具有值語義的語言,而Java是具有引用語義的語言。 在 Java 中,當您創建原始類型以外的任何變量時,您創建的不是該類型的對象,而是對此類對象的引用。 相反,在 C++ 中,相同的構造指的是一個實際的對象。
如果您牢記這一點,就很容易理解為什么以下內容不可能奏效:
class Base {
Derived d;
};
class Derived : Base {};
C++ 中的第一個定義意味着對象 Base 在內部(不是通過引用)包含一個 Derived 類型的對象。 同時,Derived 通過繼承包含一個 Base 類型的子對象。
這意味着 Derived 包含一個 Base 包含一個 Derived 包含一個 Base ...... Base 或 Derived 的大小是多少?
在具有引用語義的語言中,或者在 C++ 中,如果您使用指針,那都不是問題。 Base 對象包含一個指向Derived 的引用/指針。 Derived 通過繼承包含一個 Base 子對象。 Base 的大小是眾所周知的:所有其他字段加上引用/指針的大小。 Derived 的大小是 Base 的大小加上添加的任何額外成員的大小。
安德烈亞斯擊敗了我的正確答案,但我只想補充一點,Java 代碼之所以有效只是因為 Java 對象是由指針隱式持有的(因此B b = new B(...);
語句散布在整個 Java 代碼中),即使它看起來不像。 您的原始 C++ 代碼不起作用(即使添加了 B 類的前向聲明),因為編譯器不知道 B 對象有多大,因此也不知道包含它的 A 對象有多大。 另一方面,所有指針都具有相同的大小(無論指向類型如何),因此當您將 B 對象替換為 A 類中的 B 對象的指針時,編譯器不會出現此類問題。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.