Dies ist eine Frage, die ich beim Lesen this section on learncpp.com begegnete. Ich habe den hier aufgelisteten Code verwendet und dann geringfügige Änderungen zum Testen vorgenommen.Aufrufen von Konstruktoren während der virtuellen Vererbung mit C++
Hintergrund
Virtuelle Vererbung schafft eine gemeinsame Referenz auf die Basisklasse, die zwei Effekte hat.
Zuerst entfernt es Mehrdeutigkeit, da nur einmal Kopie der Mitglieder der Basis erstellt werden (z. B. Hinzufügen einer print() - Funktion zu PoweredDevice und Aufrufen von es in main() würde andernfalls einen Compilerfehler verursachen).
Zweitens ist die am weitesten abgeleitete Klasse verantwortlich für den Aufruf des Basiskonstruktors. Wenn eine der Zwischenklassen versucht, den Basiskonstruktor in einer Initialisierungsliste aufzurufen, sollte der Aufruf ignored sein.
Das Problem
Wenn ich kompilieren und den Code ausführen, gibt sie:
PoweredDevice: 3
PoweredDevice: 3
Scanner: 1
PoweredDevice: 3
Printer: 2
Es zurückkehren sollte:
PoweredDevice: 3
Scanner: 1
Printer: 2
Wenn ich folge der Ausführung GDB mit (7.11 .1), zeigt es, dass die Zwischenfunktionen auch PoweredDevice über die Initialisierungsliste aufrufen - diese sollten jedoch ignoriert werden. Diese mehrfache Initialisierung von PoweredDevice führt nicht zur Mehrdeutigkeit von Membern, macht mir aber Probleme, weil Code mehrfach ausgeführt wird, wenn er nur einmal vorkommen sollte. Für ein komplizierteres Problem wäre es mir nicht bequem, virtuelle Vererbung zu verwenden.
Warum initialisieren diese Zwischenklassen noch immer die Base? Ist es eine Eigenart mit meinem Compiler (gcc 5.4.0) oder missverstehe ich, wie die virtuelle Vererbung funktioniert?
bearbeiten: Code
#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;
}
was "leichte Änderungen" haben Sie gemacht? Trotzdem solltest du den Code hier posten – user463035818
Willkommen bei Stack Overflow! Bitte ** [edit] ** Ihre Frage mit einem [mcve] oder [SSCCE (kurz, eigenständiges, korrektes Beispiel)] (http://sscce.org) – NathanOliver
Der Code in einer Bearbeitung hinzugefügt.Von mir überprüfte Varianten enthielten Elementwerte und Funktionen in der Basisklasse, einschließlich verschiedener Zugriffsspezifizierer. Ich habe auch versucht, virtuelle Vererbung Zugriff Ebenen zu ändern. –