簡體   English   中英

刪除構造函數繼承

[英]deleted constructor inheritance

構造函數繼承的要求之一是,派生類不能具有具有相同簽名的任何構造函數。 但是,我不確定刪除的函數在這些規則下的行為。

class Foo
{
    public:
    Foo() = delete;
    Foo(const Foo& a_Foo) = delete;
    Foo(int a_Value) : m_Value(a_Value) {}

    private:
    int m_Value;
};

class Bar : public Foo
{
    public:
    using Foo::Foo;
    Bar() : Foo(7) {};
    Bar(const Bar& a_Bar) : Foo(12) {};
};
  • 刪除的構造函數是否完全繼承?
  • 如果是這樣, Bar()Foo()具有相同的簽名,這會使代碼無效嗎?
  • 您可能會說Foo(const Foo& a_Foo)Bar(const Bar& a_Bar)具有不同的簽名。 復制構造函數在構造函數繼承下如何表現?

默認,復制和移動構造函數不被繼承,繼承構造函數也不能隱式聲明派生類的副本或移動構造函數。 同樣,如果派生類中已經存在具有相同簽名的構造函數,則繼承的構造函數聲明實際上只會“跳過”基類構造函數。

對於繼承的構造函數候選集中的每個非模板構造函數,除了不帶參數的構造函數或具有單個參數的復制/移動構造函數之外,除非具有用戶聲明的構造函數,否則該構造函數將隱式聲明為具有相同的構造函數特性完整類中出現使用聲明的簽名相同,否則構造函數將是該類的默認,復制或移動構造函數。

([class.inhctor] / 3)

另外,如果刪除了相應的基類構造函數,則繼承的構造函數也會被刪除。

這樣聲明的構造函數與X的相應構造函數具有相同的訪問權限。 如果刪除了X的相應構造函數,則將其刪除(8.4)。 繼承的構造函數不得顯式實例化(14.7.2)或顯式專門化(14.7.3)。

([class.inhctor] / 4)

Foo構造函數被刪除,因此您不能定義使用已刪除的Foo構造函數的Bar類的構造函數。 在這里談論繼承是沒有意義的,因為您永遠無法創建使用已刪除的Foo構造函數的Bar類的對象。

刪除的構造函數是否完全繼承?

否。它們被刪除,沒有任何可繼承的。

如果是這樣,Bar()和Foo()具有相同的簽名,這會使代碼無效嗎?

默認構造函數不能被繼承。

您可能會說Foo(const Foo&a_Foo)和Bar(const Bar&a_Bar)具有不同的簽名。 復制構造函數在構造函數繼承下如何表現?

復制構造函數也不能被繼承。

考慮以下示例:

class Symbol {
  public:
    Symbol() = delete;
    Symbol(char ch) : c{ch} {}
  private:
    char c;
    //
};


class Derived : Symbol {
  public:
  private:
    int i;
};


class NotDerived {
  public:
  private:
    int i;
};

以下行將無法編譯。 您不能使用已刪除的構造函數創建類的對象。 每個人都知道。

// Can't create an object because of deleted constructor.
Symbol sym;

但是,您可以使用重載的構造函數創建基類的對象:

// Parametrized constructor, this one is fine.
Symbol sym_char('a');

使用: public繼承的Derived類繼承了Symbol基類的所有內容,包括已刪除的構造方法。 實際上,如果Symbol類具有刪除的構造函數,則不允許您使用默認構造函數創建該類的對象,那么從邏輯上講, Derived類也應禁止您使用刪除的構造函數來創建該類的對象。

//  note: default constructor of 'Derived' is implicitly deleted because base class 'Symbol' has a deleted default constructor
//  The deleted consturctor is inherited from the base class.
Derived d;

Derived類繼承了Symbol類的所有方法,包括任何刪除的構造函數!

如果刪除繼承語句,請注意繼承的已刪除構造函數將消失。 沒有再刪除的構造函數。 現在,默認編譯器生成的默認構造函數又回來了,因為刪除的構造函數不會覆蓋它。

// No deleted constructor: works
NotDerived nd;

NotDerived類具有編譯器生成的默認構造函數,因為它沒有從任何東西繼承。 Derived類沒有默認的構造函數,它具有刪除的構造函數,因為它繼承自具有刪除的構造函數的類。

因此,正如我們在上述實驗中看到的那樣,是的,基本類中的所有方法( 包括已刪除方法)都將繼承到派生類中。 這意味着在基類中被刪除的構造函數確實會繼承到派生類中!

暫無
暫無

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

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