簡體   English   中英

c ++基類包含派生類的實例

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

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM