簡體   English   中英

如何調用基類構造函數?

[英]How do I call the base class constructor?

最近,我用 Java 做了很多編程。 在那里,您使用super().調用繼承自的類super(). (你們可能都知道。)

現在我有一個 C++ 類,它有一個帶有一些參數的默認構造函數。 例子:

class BaseClass {
public:
    BaseClass(char *name); .... 

如果我繼承了這個類,它會警告我沒有合適的默認構造函數可用。 那么,在 C++ 中是否有像super()這樣的東西,還是我必須定義一個函數來初始化所有變量?

您可以在子類的構造函數的初始化列表中執行此操作。

class Foo : public BaseClass {
public:
    Foo() : BaseClass("asdf") {}
};

在初始化任何成員之前,必須在那里調用帶有參數的基類構造函數。

在頭文件中定義一個基類:

class BaseClass {
public:
    BaseClass(params);
};

然后將派生類定義為繼承 BaseClass:

class DerivedClass : public BaseClass {
public:
    DerivedClass(params);
};

在源文件中定義 BaseClass 構造函數:

BaseClass::BaseClass(params)
{
     //Perform BaseClass initialization
}

默認情況下,派生構造函數只調用沒有參數的默認基構造函數; 所以在這個例子中,基類的構造並不時自動派生構造函數被調用調用,但它可以簡單地用冒號之后加入基類的構造的語法來實現( : )。 定義一個派生構造函數,自動調用其基構造函數:

DerivedClass::DerivedClass(params) : BaseClass(params)
{
     //This occurs AFTER BaseClass(params) is called first and can
     //perform additional initialization for the derived class
}

BaseClass構造函數在DerivedClass構造函數之前被調用,如果需要,可以將相同/不同的參數params轉發到基類。 這可以嵌套用於更深的派生類。 派生構造函數必須只調用一個基構造函數。 析構函數以調用構造函數的相反順序自動調用。

編輯:如果您從任何virtual類繼承,則此規則有一個例外,通常是為了實現多重繼承菱形繼承 那么你必須顯式調用所有virtual基類的基構造函數並顯式傳遞參數,否則它只會調用它們的默認構造函數而沒有任何參數。 請參閱: 虛擬繼承 - 跳過構造函數

您必須使用初始化程序:

class DerivedClass : public BaseClass
{
public:
  DerivedClass()
    : BaseClass(<insert arguments here>)
  {
  }
};

這也是您構造沒有構造函數(或您想要初始化)的類成員的方式。 任何未提及的成員將被默認初始化。 例如:

class DerivedClass : public BaseClass
{
public:
  DerivedClass()
    : BaseClass(<insert arguments here>)
    , nc(<insert arguments here>)
    //di will be default initialized.
  {
  }

private:
  NeedsConstructor nc;
  CanBeDefaultInit di;
};

指定成員的順序無關緊要(盡管構造函數必須在前),但它們的構造順序是聲明順序。 所以nc總是在di之前構造。

關於super的替代品; 在大多數情況下,您會在派生類的初始化列表中使用基類,或者在其他地方工作並且派生類重新定義數據成員時使用Base::someData語法。

struct Base
{
    Base(char* name) { }
    virtual ~Base();
    int d;
};

struct Derived : Base
{
    Derived() : Base("someString") { }
    int d;
    void foo() { d = Base::d; }
};

在初始化列表中使用基類的名稱。 初始化列表出現在方法體之前的構造函數簽名之后,可用於初始化基類和成員。

class Base
{
public:
  Base(char* name)
  {
     // ...
  }
};

class Derived : Base
{
public:
  Derived()
    : Base("hello")
  {
      // ...
  }
};

或者,有些人使用的模式是自己定義“超級”或“基礎”。 也許一些喜歡這種技術的人是轉向 C++ 的 Java 開發人員。

class Derived : Base
{
public:
  typedef Base super;
  Derived()
    : super("hello")
  {
      // ...
  }
};

C++ 中沒有 super() 。 您必須按名稱顯式調用 Base Constructor。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

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