[C++] Warum haben wir keinen virtuellen Konstruktor in C ++?


Answers

Virtuelle Funktionen bieten grundsätzlich polymorphes Verhalten. Das heißt, wenn Sie mit einem Objekt arbeiten, dessen dynamischer Typ sich von dem statischen (Kompilierzeit) -Typ unterscheidet, auf den es verweist, bietet es ein Verhalten, das für den tatsächlichen Typ des Objekts anstelle des statischen Typs des Objekts geeignet ist.

Versuchen Sie nun, dieses Verhalten auf einen Konstruktor anzuwenden. Wenn Sie ein Objekt konstruieren, ist der statische Typ immer gleich dem tatsächlichen Objekttyp seit:

Um ein Objekt zu konstruieren, benötigt ein Konstruktor den genauen Typ des Objekts, das er erzeugen soll. [...] Außerdem können Sie keinen Zeiger auf einen Konstruktor haben

(Bjarne Stroustup (P424 Die C ++ Programmiersprache SE))

Question

Warum hat C ++ keinen virtuellen Konstruktor?




Sie sollten auch keine virtuelle Funktion innerhalb Ihres Konstruktors aufrufen. Siehe: http://www.artima.com/cppsource/nevercall.html

Außerdem bin ich mir nicht sicher, ob Sie wirklich einen virtuellen Konstruktor benötigen. Sie können polymorphe Konstruktion ohne es erreichen: Sie können eine Funktion schreiben, die Ihr Objekt gemäß den erforderlichen Parametern konstruieren wird.




Virtuelle Funktionen in C ++ sind eine Implementierung von Laufzeitpolymorphismus, und sie funktionieren übersteuernd. Im Allgemeinen wird das virtual Schlüsselwort in C ++ verwendet, wenn Sie dynamisches Verhalten benötigen. Es funktioniert nur, wenn das Objekt existiert. Während Konstruktoren zum Erstellen der Objekte verwendet werden. Konstruktoren werden zum Zeitpunkt der Objekterstellung aufgerufen.

Wenn Sie also den Konstruktor gemäß der virtuellen Schlüsselwortdefinition als virtual erstellen, sollte das vorhandene Objekt vorhanden sein, aber der Konstruktor wird verwendet, um das Objekt zu erstellen, so dass dieser Fall niemals existiert. Sie sollten den Konstruktor also nicht als virtuell verwenden.

Wenn wir also versuchen, den virtuellen Konstruktor-Compiler zu deklarieren, werfen wir einen Fehler:

Konstruktoren können nicht als virtuell deklariert werden




Können wir es einfach nicht sagen ... Wir können Konstruktoren nicht erben. Es hat also keinen Sinn, sie als virtuell zu deklarieren, weil das Virtuelle Polymorphismus bietet.




Ein virtueller C ++ - Konstruktor ist nicht möglich. Beispielsweise können Sie einen Konstruktor nicht als virtuell kennzeichnen. Versuchen Sie diesen Code

#include<iostream.h>
using namespace std;
class aClass
{
    public:
        virtual aClass()
        {   
        }  
};
int main()
{
    aClass a; 
}

Es verursacht einen Fehler. Dieser Code versucht, einen Konstruktor als virtuell zu deklarieren. Versuchen wir nun zu verstehen, warum wir ein virtuelles Schlüsselwort verwenden. Das virtuelle Schlüsselwort wird verwendet, um einen Laufzeitpolymorphismus bereitzustellen. Versuchen Sie zum Beispiel diesen Code.

#include<iostream.h>
using namespace std;
class aClass
{
    public:
        aClass()
        {
            cout<<"aClass contructor\n";
        }
        ~aClass()
        {
            cout<<"aClass destructor\n";
        }

};
class anotherClass:public aClass
{

    public:
        anotherClass()
        {
            cout<<"anotherClass Constructor\n";
        }
        ~anotherClass()
        {
            cout<<"anotherClass destructor\n";
        }

};
int main()
{
    aClass* a;
    a=new anotherClass;
    delete a;   
    getchar(); 
}

In Haupt a=new anotherClass; reserviert einen Speicher für anotherClass in einem Zeiger, der als Typ von aClass deklariert aClass bewirkt, dass der Konstruktor (In aClass und anotherClass ) automatisch aClass anotherClass wir den Konstruktor nicht als virtuell markieren. Denn wenn ein Objekt erstellt wird, muss es folgen die Kette der Schöpfung (dh zuerst die Basis und dann die abgeleiteten Klassen). Aber wenn wir versuchen, ein delete a; zu delete a; Es ruft nur den Basisdestruktor auf. Daher müssen wir den Destruktor mit einem virtuellen Schlüsselwort behandeln. Also virtueller Konstruktor ist nicht möglich, aber virtueller Destruktor ist. Danke




Abgesehen von semantischen Gründen gibt es keine vtable, bis das Objekt konstruiert ist, was eine virtuelle Bezeichnung nutzlos macht.




Wenn Sie logisch darüber nachdenken, wie Konstruktoren arbeiten und was die Bedeutung / Verwendung einer virtuellen Funktion in C ++ bedeutet, werden Sie feststellen, dass ein virtueller Konstruktor in C ++ bedeutungslos wäre. Das Deklarieren von etwas virtuellem in C ++ bedeutet, dass es von einer Unterklasse der aktuellen Klasse überschrieben werden kann, jedoch wird der Konstruktor aufgerufen, wenn das Objekt erstellt wird. Zu diesem Zeitpunkt können Sie keine Unterklasse der Klasse erstellen Erstellen der Klasse, so dass es niemals nötig wäre, einen Konstruktor virtuell zu deklarieren.

Und ein anderer Grund ist, dass die Konstruktoren den gleichen Namen wie der Klassenname haben und wenn wir den Konstruktor als virtuell deklarieren, dann sollte er in seiner abgeleiteten Klasse mit demselben Namen neu definiert werden, aber Sie dürfen nicht den gleichen Namen zweier Klassen haben. Es ist also nicht möglich, einen virtuellen Konstruktor zu haben.




Sie können ein Beispiel und den technischen Grund finden, warum es in @stefans Antwort nicht erlaubt ist. Nun eine logische Antwort auf diese Frage ist meiner Meinung nach:

Die Hauptverwendung von virtuellem Schlüsselwort besteht darin, polymorphes Verhalten zu aktivieren, wenn wir nicht wissen, auf welchen Typ des Objekts der Zeiger der Basisklasse zeigt.

Aber denken Sie daran ist primitiver Weg, für die Verwendung virtueller Funktionalität benötigen Sie einen Zeiger. Und was benötigt ein Zeiger? Ein Objekt zum Zeigen! (unter Berücksichtigung der korrekten Ausführung des Programms)

Wir benötigen also grundsätzlich ein Objekt, das bereits irgendwo im Speicher vorhanden ist (wir befassen uns nicht damit, wie der Speicher zugewiesen wurde, es kann zur Kompilierungszeit oder zur Laufzeit sein), so dass unser Zeiger korrekt auf dieses Objekt zeigen kann.

Denken Sie nun an die Situation in dem Moment, in dem dem Objekt der zu spitzenden Klasse etwas Speicher zugewiesen wird -> Sein Konstruktor wird automatisch an dieser Instanz selbst aufgerufen!

So können wir sehen, dass wir uns nicht wirklich darum sorgen müssen, dass der Konstruktor virtuell ist, denn in jedem Fall, in dem Sie ein polymorphes Verhalten verwenden möchten, wäre unser Konstruktor bereits ausgeführt worden, um unser Objekt für die Verwendung bereit zu machen!




zwei Gründe, die ich mir vorstellen kann:

Technischer Grund

Das Objekt existiert erst, nachdem der Konstruktor beendet wurde. Damit der Konstruktor über die virtuelle Tabelle ausgelöst wird, muss ein vorhandenes Objekt mit einem Zeiger auf die virtuelle Tabelle vorhanden sein, aber wie kann ein Zeiger auf die virtuelle Tabelle existieren, wenn das Objekt vorhanden ist existiert noch nicht? :)

Logikgrund

Sie verwenden das Schlüsselwort virtual, wenn Sie ein etwas polymorphes Verhalten deklarieren möchten. Aber es gibt nichts, das mit Konstruktoren polymorph ist, Konstruktorarbeit in C ++ ist, einfach eine Objektdaten in den Speicher zu legen. Da virtuelle Tabellen (und Polymorphismen im Allgemeinen) sich allesamt auf polymorphes Verhalten und nicht auf polymorphe Daten beziehen, hat es keinen Sinn, einen virtuellen Konstruktor zu deklarieren.




Obwohl das Konzept der virtuellen Konstruktoren nicht gut passt, da der Objekttyp die Voraussetzung für die Objekterstellung ist, ist es nicht vollständig überbestimmt.

GOFs Entwurfsmuster "Factory-Methode" nutzt das "Konzept" des virtuellen Konstruktors, das sich in bestimmten Design-Situationen befindet.