這是我在閱讀this section on learncpp.com時遇到的問題。我使用了這裏列出的代碼,然後對測試做了輕微的改動。用C++虛擬繼承期間調用構造函數
背景
虛繼承創建一個共同的參考基類,其具有兩個效果。首先,它消除了歧義,因爲只有一次創建基本成員的副本(例如,向PoweredDevice添加print()函數並在main()中調用它)否則會導致編譯器錯誤)。
其次,派生最多的類將負責調用基構造函數。如果其中一箇中間類嘗試調用初始化列表中的基礎構造函數,則該調用應爲ignored。
的問題
當我編譯和運行代碼,它返回:
PoweredDevice: 3
PoweredDevice: 3
Scanner: 1
PoweredDevice: 3
Printer: 2
它應該返回:
PoweredDevice: 3
Scanner: 1
Printer: 2
當我按照使用GDB的執行(7.11 .1),它顯示中間函數也通過初始化列表調用PoweredDevice - 但這些應該被忽略。這個多次初始化的PoweredDevice不會導致任何成員的歧義,但確實麻煩了我,因爲代碼多次執行時應該只發生一次。對於更復雜的問題,我不會習慣使用虛擬繼承。
爲什麼這些中間類仍在初始化基礎?這是一個與我的編譯器(gcc 5.4.0)的怪癖還是我誤解虛擬繼承如何工作?
編輯:代碼
#include <iostream>
using namespace std;
class PoweredDevice
{
public:
int m_nPower;
public:
PoweredDevice(int nPower)
:m_nPower {nPower}
{
cout << "PoweredDevice: "<<nPower<<endl;
}
void print() { cout<<"Print m_nPower: "<<m_nPower<<endl; }
};
class Scanner : public virtual PoweredDevice
{
public:
Scanner(int nScanner, int nPower)
: PoweredDevice(nPower)
{
cout<<"Scanner: "<<nScanner<<endl;
}
};
class Printer : public virtual PoweredDevice
{
public:
Printer(int nPrinter, int nPower)
: PoweredDevice(nPower)
{
cout<<"Printer: "<<nPrinter<<endl;
}
};
class Copier : public Scanner, public Printer
{
public:
Copier(int nScanner, int nPrinter, int nPower)
:Scanner {nScanner, nPower}, Printer {nPrinter, nPower}, PoweredDevice {nPower}
{ }
};
int main()
{
Copier cCopier {1,2,3};
cCopier.print();
cout<<cCopier.m_nPower<<'\n';
return 0;
}
你做了什麼「輕微的改動」?無論如何,你應該在這裏發佈代碼 – user463035818
歡迎來到堆棧溢出!請** [編輯] **用[mcve]或[SSCCE(Short,Self Contained,Correct Example)](http://sscce.org)的問題 – NathanOliver
在編輯中添加了代碼。我檢查過的變體包括基類中的成員值和函數,包括不同的訪問說明符。我也嘗試改變虛擬繼承訪問級別。 –