簡體   English   中英

在 C++ 中的一些其他指令之后調用基礎 class 的構造函數

[英]Calling the constructor of the base class after some other instructions in C++

據我所知,不可能調用基礎 class 的構造函數。 我知道的唯一方法是:

MyClass::MyClass(/* args */) : Base(/* args */)
{
   // ...
}

但這會在開始時調用構造函數。 有沒有辦法在構造函數的其他地方調用它? 像這樣的東西:

MyClass::MyClass(/* args */)
{
   // ... instructions
   Base::Base(/* args */);
   // ... other_instructions
}

根據this 調用超類構造函數的規則是什么? 問題我明白沒有辦法,但我在這里讀到,我猜這是可能的,但如果我嘗試,我會得到:

error: invalid use of 'class Base'.

難道我做錯了什么? 是否有可能以某種方式做到這一點,或者是否有其他可能的解決方案來滿足這種需求?

謝謝!

編輯:我知道我忘記了一個關鍵點:基礎 class 是框架的一部分,因此如果可能的話,最好不要修改它。

如果基本的 class 構造函數至少需要一個參數,則可以像這樣使用輔助函數 function:

int DoStuffBeforeCtorAndForwardInt(int arg, Foo foo)
{
    DoStuff(arg, foo);
    return arg;
}

MyClass::MyClass(int arg, Foo foo)
    : Base(DoStuffBeforeCtorAndForwardInt(arg, foo))
{
   // ...
}

如果要默認初始化基本 class,可以使用 copy-ctor 復制默認初始化的基本 class 實例:

Base DoStuffBeforeCtorAndReturnDefaultBase(int arg, Foo foo)
{
    DoStuff(arg, foo);
    return Base();
}

MyClass::MyClass(int arg, Foo foo)
    : Base(DoStuffBeforeCtorAndReturnDefaultBase(arg, foo))
{
   // ...
}

或者,如果Base不必是第一個基礎 class,您可以從幫助程序 class 派生MyClass

MyClass::MyClass(/* ... */)
    : DoStuffHelperClass(/* ... */),
    Base(/* ... */)
{
   // ...
}

以上所有要求您所做的“東西”不依賴於即將初始化的 object(即,函數不能安全地成為成員函數,您也不能安全地將this作為參數傳遞給它們)。

這意味着您可以執行一些日志記錄或類似操作,但是您也可以在初始化基本 class 之后再執行此操作。

編輯,除了 DoStuffHelperClass 解決方案,您當然可以在 DoStuffHelperClass 中擁有成員,訪問它們等等)


雖然我不得不說我不記得曾經使用/需要/想要這樣的東西。 對於您正在嘗試做的事情,很可能還有另一種(首選)解決方案。

使用base-from-member 習慣用法在“真實”基礎 class(即 Base)的 ctor 之前運行您的代碼:

struct Base {
  Base(string, int);
};

struct DerivedDetail {
  DerivedDetail() {
    value = compute_some_value();
    value += more();
    value += etc();
    other = even_more_code(value);
  }
  string value;
  int other;
};

struct Derived : private DerivedDetail, Base {
  Derived() : Base(value, other) {}
  // In particular, note you can still use this->value and just
  // ignore that it is from a base, yet this->value is still private
  // within Derived.
};

即使您在 DerivedDetail 中沒有所需的實際成員,這也有效。 如果您在 Base 的 ctor 之前詳細說明您必須做什么,那么我可以舉一個更好的例子。

基礎 class 始終在您自己的 class 開始構建之前完全構建。 如果您需要對基礎 class 的 state 進行更改,則必須在構建后明確執行此操作。

例子:

MyClass::MyClass()
{
    // Implicit call to Base::Base()

    int result = computeSomething();
    Base::setResult(result);

    // ... 
}

除了已經編寫好的解決方案,您還可以使用 static 構造函數 function 並將MyClass的構造函數設為私有。

class QtBase{
  // ...
};

class MyClass : public QtBase{
public:
  // copy ctor public
  MyClass(MyClass const& other);

  static MyClass Create(/*args*/){
    // do what needs to be done
    int idata;
    float fdata;
    // work with idata and fdata as if they were members of MyClass
    return MyClass(idata,fdata); // finally make them members
  }

  static MyClass* New(/*args*/){
    int idata;
    float fdata;
    // work with idata and fdata as if they were members of MyClass
    return new MyClass(idata,fdata); // finally make them members
  }

private:
  // ctor private
  MyClass(int a_idata, float a_fdata)
    : idata(a_idata)
    , fdata(a_fdata)
  {}

  int idata;
  float fdata;
};

現在您必須創建MyClass的實例:

MyClass obj = MyClass::Create(/*args*/);

或者

MyClass* ptr = MyClass::New(/*args*/);

不,因為它不是類型安全的。
考慮你有:一個 class A和一個變量A.var
現在考慮B繼承自A ,並在A初始化之前使用var 你會得到一個運行時錯誤,語言想要防止這種情況發生。 因此必須首先初始化超類構造函數。

不,你不能那樣做,正如其他人在他們之前的回答中所描述的那樣。

你唯一的機會是組合, MyClass使用Base class 作為成員字段的 IOW:

class MyClass {
public:
   /** the methods... */

private:
   Base* _base;
};

因此,您可以稍后在獲得所需信息時初始化_base 無論如何,我不知道這是否適用於您的場景。

不,這是不可能的,因為構造函數調用的順序是由標准嚴格定義的。 必須先執行基本 class ctor,然后才能執行派生 class ctor。

暫無
暫無

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

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