簡體   English   中英

使用C ++在虛擬繼承期間調用構造函數

[英]Invoking constructors during virtual inheritance with C++

這是我在learncpp.com上閱讀本節時遇到的一個問題。 我使用了這里列出的代碼,然后對測試做了一些改動。

背景

虛擬繼承創建對基類的公共引用,它具有兩個效果。

首先,它消除了歧義,因為只創建了一個基礎成員的副本(例如,向PoweredDevice添加print()函數並在main()中調用它否則會導致編譯器錯誤)。

其次,派生程度最高的類負責調用基礎構造函數。 如果其中一個中間類嘗試在初始化列表中調用基本構造函數,則應忽略該調用。

問題

當我編譯並運行代碼時,它返回:

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;
}

這似乎是一個GCC錯誤,當統一初始化與虛擬繼承一起使用時觸發。


如果我們改變:

Copier(int nScanner, int nPrinter, int nPower)
    :Scanner {nScanner, nPower}, Printer {nPrinter, nPower}, PoweredDevice {nPower}
{ }

至:

Copier(int nScanner, int nPrinter, int nPower)
    :Scanner (nScanner, nPower), Printer (nPrinter, nPower), PoweredDevice (nPower)
{ }

錯誤消失,並且行為符合預期:

PoweredDevice: 3
Scanner: 1
Printer: 2
Print m_nPower: 3
3

Clang和Visual Studio都能夠正確編譯原始代碼,並提供預期的輸出。

暫無
暫無

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

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