2013-06-19 6 views
6

Ich habe versucht, den Implementierungscode von "final" in cpp zu verstehen:"final" -Klasse Implementierung in C++

folgenden ist der Code:

/* A program with compilation error to demonstrate that Final class cannot 
    be inherited */ 

class Final; // The class to be made final 

class MakeFinal // used to make the Final class final 
{ 
private: 
    MakeFinal() { cout << "MakFinal constructor" << endl; } 
friend class Final; 
}; 

class Final : virtual MakeFinal 
{ 
public: 
    Final() { cout << "Final constructor" << endl; } 
}; 

class Derived : public Final // Compiler error 
{ 
public: 
    Derived() { cout << "Derived constructor" << endl; } 
}; 

int main(int argc, char *argv[]) 
{ 
    Derived d; 
    return 0; 
} 

Ausgang: Compilerfehler

In constructor 'Derived::Derived()': 
error: 'MakeFinal::MakeFinal()' is private 

In diesem konnte ich die Logik der virtuellen Übernahme der MakeFinal-Klasse nicht verstehen. Wir könnten es einfach (makeFinal-Klasse) als public geerbt haben und selbst in diesem Fall hätten wir es nicht weiter erben können (weil der Makefile-Konstruktor privat ist und nur die Final-Klasse, die sein Freund ist, darauf zugreifen kann) .

Irgendein Zeiger ??

+0

Haben Sie es tatsächlich mit nicht-virtueller Vererbung versucht? – hvd

+1

Ein 'privater Konstruktor' hat nichts damit zu tun, dass er nicht erben kann oder nicht. Ich verstehe wirklich nicht, was du versuchst zu tun. –

+0

@ Bash.d Sicher ist es. Sie können nicht von einer Klasse ableiten, wenn dies einen Aufruf eines Konstruktors erfordert, auf den nicht zugegriffen werden kann (weil der Konstruktor privat ist). – hvd

Antwort

11

Es würde nicht funktionieren. Nicht-virtuelle Basisklassen werden immer von der Klasse initialisiert, die unmittelbar von ihnen abgeleitet ist. Das heißt, wenn das Szenario wie folgt dar:

class Final : public MakeFinal 
{ 
public: 
    Final() {} 
}; 

class Derived : public Final 
{}; 

dann der Ctor von Derived nur initialisiert Final, was in Ordnung ist (Final hat eine öffentliche Ctor). Final 's ctor initialisiert dann MakeFinal, was auch möglich ist, da Final ein Freund ist.

Bei virtuellen Basisklassen ist die Regel jedoch anders. Alle virtuellen Basisklassen werden vom ctor des am meisten abgeleiteten Objekts initialisiert. Das heißt, wenn eine Instanz von Final erstellt wird, ist es Final 's ctor, die MakeFinal initialisiert. Wenn Sie jedoch versuchen, eine Instanz von Derived zu erstellen, muss es Derived 's ctor sein, der MakeFinal initialisiert. Und das ist unmöglich, wegen MakeFinal 's privaten ctor.

Beachten Sie auch, dass C++ 11 das Schlüsselwort final für Klassen (und virtuelle Funktionen) eingeführt hat.

+0

Danke @ Angew.Kannst du mich bitte zu einer Ressource/Link verweisen, wo ich weitere Details darüber finden kann, wie virtuelle Vererbung tatsächlich in gcc implementiert wird? Meine andere Absicht ist es, einen Einblick zu bekommen, wie das Diamantproblem tatsächlich durch den Compiler gelöst wird. – pjain

+0

@pjain Sorry, ich kann dir hier nicht helfen. Ich weiß wenig über Compilerimplementierungen. – Angew