簡體   English   中英

稍后在 C++ 中調用基類構造函數(不在初始化列表中)

[英]Call a base class constructor later (not in the initializer list) in C++

我正在繼承一個類,我想調用它的構造函數之一。 但是,在調用它之前我必須處理一些東西(不需要任何基類的東西)。 有什么辦法可以稍后調用它而不是在初始化列表中調用它? 我相信這可以在 Java 和 C# 中完成,但我不確定 C++。

我需要在構造函數上傳遞的數據不能在以后重新分配,所以我不能只調用一個默認構造函數並稍后對其進行初始化。

有什么辦法可以稍后調用它而不是在初始化列表中調用它?

不,你不能。 必須在初始化列表中調用基類構造函數,並且必須首先調用它。

事實上,如果你在那里省略它,編譯器只會隱式地添加調用。

我相信這可以在 Java 和 C# 中完成,但我不確定 C++。

C# 和 Java 都不允許這樣做。

但是,您可以做的是調用一個方法作為基類構造函數調用的參數 然后在構造函數之前處理它:

class Derived {
public:
    Derived() : Base(some_function()) { }

private:
    static int some_function() { return 42; }
};

正如回答的幾個人所說,您不能延遲基類構造函數的調用,但Konrad 給出了一個很好的答案,可以很好地解決您的問題。 但是,這確實有其缺點(例如,當您需要使用其計算共享中間結果的值來初始化多個函數時),所以為了完整起見,這是解決固定初始化順序問題的另一種方法,通過使用它。

給定初始化的固定順序,如果您可以控制派生類(以及您將如何擺弄它的一個 ctors?),您可以潛入一個私有基類,以便它在另一個類之前被初始化基,然后可以使用私有基已經計算的值進行初始化:

class my_dirty_little_secret {
  // friend class the_class;
public: 
  my_dirty_little_secret(const std::string& str)
  {
    // however that calculates x, y, and z from str I wouldn't know
  }
  int x;
  std::string y;
  float z;
};

class the_class : private my_dirty_little_secret // must be first, see ctor
                , public the_other_base_class {
  public:
    the_class(const std::string str)
      : my_dirty_little_secret(str)
      , the_other_base_class(x, y, z)
    {
    }
  // ...
};

my_dirty_little_secret類是私有基礎,因此the_class用戶無法使用它,它的所有內容也是私有的,顯式友誼僅授予the_class訪問權限。 但是,由於它首先列在基類列表中,因此它將在the_other_base_class之前可靠地構造,因此無論它計算什么,都可以用來初始化它。
基類列表中的一個很好的注釋有望防止其他人通過重構破壞事物。

恕我直言,我認為不可能以您提到的方式推遲調用基類構造函數。

哇,我們都曾經年輕過。 這個答案不起作用,所以不要使用它。 內容留作歷史用途。

如果您可以完全控制基類,我建議添加一個受保護的方法來進行類初始化,使其成為虛擬的,並在調用其基類之前將派生類的實現細節放入其中:

class Base
{
public:
    Base()
    {
        Initialize();
    }
protected:
    virtual void Initialize()
    {
        //do initialization;
    }
};

class Derived : Base
{
public:

    Derived() : Base()
    {
    }
protected:
    virtual void Initialize()
    {
        //Do my initialization
        //call base
        Base::Initialize();
    }
};

根據@Konrad 的建議,另一種選擇是使用靜態方法來構造對象,例如:

class Derived {
public:
    Derived(int p1, int p2, int p3) : Base(p1, p2) { }

    static Derived* CreateDerived(int p3) { return new Derived(42, 314, p3); }
};

我發現這在從庫中擴展類並具有多個要覆蓋的參數時很有用。 您甚至可以將構造函數設為私有

struct base{
   base(int x){}
};

struct derived : base{
   derived(int x) : base(x){}
};

這就是在 C++ 中從派生類的初始化列表中調用基類構造函數的方式。

暫無
暫無

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

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