Frage

Warum C ++ keinen virtuellen Konstruktor haben?

Keine korrekte Lösung

Andere Tipps

Hören Sie es aus dem Mund :) das Pferd.

Von Bjarne Stroustrup C ++ Stil und Technik FAQ Warum nicht wir haben virtueller Bauer?

  

Ein virtueller Aufruf ist ein Mechanismus zu bekommen Arbeit teilweise getan gegeben   Information. Insbesondere „virtuelle“ ermöglicht es uns, eine Funktion aufzurufen   nur alle Schnittstellen und nicht die genaue Art des Objekts zu kennen. Zu   erstellen Sie ein Objekt, das Sie alle Informationen benötigen. Insbesondere Sie   müssen die genaue Art der wissen, was Sie erstellen möchten. Folglich,   a „zu einem Konstruktor rufen“ kann nicht virtuell sein.

Der FAQ-Eintrag geht auf dem Code für eine Art und Weise zu geben, um dieses Ziel ohne einen virtuellen Konstruktor zu erreichen.

Virtuelle Funktionen bieten grundsätzlich polymorphes Verhalten. Das heißt, wenn Sie mit einem Objekt, dessen dynamischer Typ arbeiten ist anders als die statischen (Zeit kompilieren) geben, mit denen sie genannt wird, bietet es Verhalten, das für die ist Typ des Objekts statt geeignet ist der statische Typ des Objekts.

Versuchen Sie nun, diese Art von Verhalten zu einem Konstruktor anzuwenden. Wenn Sie ein Objekt der statische Typ immer das gleiche wie der tatsächliche Objekttyp konstruieren da:

  

Um ein Objekt zu konstruieren, muss ein Konstruktor den genauen Typ des Objekts, es zu schaffen ist [...] Darüber hinaus [...] Sie nicht einen Zeiger auf einen Konstruktor haben kann

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

Wir tun, es ist einfach nicht einen Konstruktor: -)

struct A {
  virtual ~A() {}
  virtual A * Clone() { return new A; }
};

struct B : public A {
  virtual A * Clone() { return new B; }
};

int main() {

   A * a1 = new B;
   A * a2 = a1->Clone();    // virtual construction
   delete a2;
   delete a1;
}

Semantic Gründe beiseite, gibt es keine Vtable bis, nachdem das Objekt aufgebaut ist, also eine virtuelle Bezeichnung unbrauchbar zu machen.

Zusammenfassung : Die C ++ Standard- könnte geben Sie eine Notation und Verhalten für "virtuellen Konstruktor" s, die für Compiler recht intuitiv und nicht zu schwer ist, um Unterstützung, aber warum eine Standard-Änderung für diese speziell machen, wenn die Funktionalität bereits sauber create() / clone() (siehe unten) durchgeführt werden kann mit? Es ist nicht annähernd so nützlich wie viele andere Sprache Vorschlag in der Pipeline.

Diskussion

Lassen Sie uns postulieren einen "virtuellen Konstruktor" -Mechanismus:

Base* p = new Derived(...);
Base* p2 = new p->Base();  // possible syntax???

In dem obigen, die erste Zeile erstellt ein Derived Objekt, so *p virtuelle Dispatch-Tabelle maßt einen „virtuellen Konstruktor“ für den Einsatz in der zweiten Zeile liefern. (Dutzende von Antworten auf dieser Seite unter Angabe „das Objekt existiert noch nicht so virtuelle Konstruktion ist unmöglich“ ist unnötig kurzsichtig konzentriert sich auf dem zu-konstruiertes Objekt.)

Die zweite Zeile postuliert die Notation new p->Base() dynamische Zuordnung und Standard Aufbau eines anderen Derived Objekt anzufordern.

Weitere Informationen:

Der Compiler müsse:

  • herauszufinden, wie viel Speicher Derived benötigt, entweder durch eine implizite virtual sizeof Funktion aufrufen oder solche Informationen, die über RTTI mit
  • Anruf operator new(size_t) zuzuteilen Speicher
  • aufrufen Derived() mit Platzierung new.

oder

  • schafft einen zusätzlichen VTable-Eintrag für eine Funktion, die dynamische Zuweisung und Konstruktion
  • kombiniert

So - es ist nicht unüberwindbar scheint virtuelle Konstrukteuren zu spezifizieren und zu implementieren, aber die Millionen-Dollar-Frage lautet: Wie wäre es besser, als das, was möglich ist in einem der vorhandenen C ++ Sprachfunktionen ...? Persönlich Ich sehe keinen Vorteil gegenüber der Lösung unten.


`clone ()` und `create ()`

Die C ++ FAQ dokumentiert einen "virtuellen Konstruktor" Idiom , enthaltend virtual create() und clone() Methoden auf Standard-Konstrukt oder copy-Konstrukt ein neues dynamisch zugeordnete Objekt:

class Shape {
  public:
    virtual ~Shape() { } // A virtual destructor
    virtual void draw() = 0; // A pure virtual function
    virtual void move() = 0;
    // ...
    virtual Shape* clone() const = 0; // Uses the copy constructor
    virtual Shape* create() const = 0; // Uses the default constructor
};
class Circle : public Shape {
  public:
    Circle* clone() const; // Covariant Return Types; see below
    Circle* create() const; // Covariant Return Types; see below
    // ...
};
Circle* Circle::clone() const { return new Circle(*this); }
Circle* Circle::create() const { return new Circle(); }

Es ist auch möglich, oder Überlastung create() zu ändern Argumente zu akzeptieren, obwohl die Klasse / Base übereinstimmen virtual Funktion Unterschrift Schnittstelle, Argumente zu überschreibt muss genau eine der Basisklasse Überlastungen entsprechen. Witen diese expliziten Benutzer bereitgestellte Einrichtungen, ist es einfach, die Protokollierung, Instrumentierung, ändert Speicherzuordnung etc ..

hinzufügen

Sie können ein Beispiel und den technischen Grund zu finden, warum es in @stefan ‚s Antwort ist nicht erlaubt. Jetzt eine logische Antwort auf diese Frage nach mir:

Der große Einsatz von virtuellem Schlüsselwort ist polymorph Verhalten zu aktivieren, wenn wir nicht wissen, welche Art des Objekts der Basisklasse Zeiger verweisen auf.

Aber denken Sie an das ist mehr primitive Art und Weise, für die virtuelle Funktion verwenden Sie einen Zeiger benötigen. Und was erfordert ein Zeiger? Ein Objekt zu Punkt! (Unter Berücksichtigung des Falles für die korrekte Ausführung des Programms)

Also, wir benötigen im Grunde ein Objekt, das in dem Speicher vorhanden ist irgendwo schon (das sind wir nicht mit, wie der Speicher zugewiesen wurde, kann es bei der Kompilierung oder jede Laufzeit sein), so dass unser Zeiger richtig auf dieses Objekt verweisen.

Nun, denken Sie an die Situation über den Moment, wenn das Objekt der Klasse hingewiesen werden soll, etwas Speicher zugewiesen wird -> Der Konstruktor wird in diesem Fall selbst automatisch aufgerufen werden

So können wir sehen, dass wir eigentlich keine Sorgen machen müssen, um über die Konstruktor virtuell ist, weil in keinem der Fälle Sie unser Konstruktor eine polymorphe Verhalten verwenden möchten, bereits ausgeführt worden wäre unsere Aufgabe bereit für den Gebrauch zu machen!

Obwohl das Konzept der virtuellen Bauer gut passt nicht in da Objekttyp für Objekterstellung Voraussetzung ist, es ist nicht komplett überstimmt.

GOF der ‚Factory-Methode‘ Entwurfsmuster nutzt das ‚Konzept‘ virtuellen Konstruktor, die in bestimmten Situationen Design handly ist.

Virtuelle Funktionen in C ++ sind eine Implementierung von Run-Time-Polymorphismus, und sie werden Funktion überwiegende tun. Im Allgemeinen wird das virtual Schlüsselwort in C ++ verwendet, wenn Sie dynamische Verhalten benötigen. Es wird nur funktionieren, wenn Objekt vorhanden ist. Während Konstrukteure die Objekte erstellen verwendet. Konstrukteurs wird zum Zeitpunkt der Objekterstellung aufgerufen werden.

Wenn Sie also den Konstruktor als virtual erstellen, gemäß dem Schlüsselwort virtual Definition, sollte vorhandenes Objekt verwenden müssen, werden aber Konstruktor verwendet, um das Objekt zu erstellen, so dass dieser Fall wird es nie geben. Sie sollten also nicht den Konstruktor als virtuelle verwenden.

Also, wenn wir versuchen, virtuellen Konstruktor Compiler werfen einen Fehler zu deklarieren:

  

Konstrukteurs kann nicht erklärt werden virtuelle

Wenn die Leute eine Frage wie diese fragen, wie ich an mich selbst denken „was passieren würde, wenn dies tatsächlich möglich wäre?“ Ich weiß wirklich nicht, was dies bedeuten würde, aber ich denke, es wäre etwas mit der Lage zu tun haben, den Konstruktor Implementierung überschreiben auf der Basis des dynamischen Typ des Objekts erstellt wird.

Ich sehe eine Reihe potenzieller Probleme. Zum einen ist nicht die abgeleitete Klasse vollständig zu der Zeit konstruiert werden, die virtuellen Konstruktor aufgerufen, so gibt es mögliche Probleme bei der Umsetzung.

Zweitens: Was würde im Fall von Mehrfachvererbung geschehen? Ihre virtuelle Konstruktor würde mehrere Male vermutlich genannt werden, würden Sie dann einen Weg Know müssen, die man genannt wurde.

Drittens, in der Regel zum Zeitpunkt der Konstruktion spricht, wird das Objekt nicht die virtuelle Tabelle vollständig aufgebaut hat, bedeutet dies, wäre es eine große Änderung in die Sprachspezifikation erfordert für die Tatsache zu berücksichtigen, dass der dynamische Typ des Objekts wäre bei Bauzeiten bekannt. Dies würde der Basisklassenkonstruktor dann erlaubt vielleicht andere virtuelle Funktionen in Bauzeiten zu nennen, mit einem nicht vollständig aufgebaut dynamischen Klassentyp.

Schließlich, wie jemand anderes darauf hingewiesen hat, können Sie eine Art virtueller Konstruktor statisch „erstellen“ oder „init“ Typ Funktionen implementieren, die im Grunde das Gleiche wie einen virtuellen Konstruktor tun tun würde.

Virtuelle Funktionen verwendet werden, um Funktionen aufzurufen, auf der Art des Objekts basierend auf den durch den Zeiger, und nicht die Art der Zeiger selbst. Aber ein Konstruktor ist nicht „aufgerufen“. Es wird nur einmal aufgerufen, wenn ein Objekt deklariert wird. So kann ein Konstruktor nicht in C gemacht virtuelle werden ++.

Sie sollten auch nicht virtuelle Funktion in Ihrem Konstruktor aufrufen. Siehe: http://www.artima.com/cppsource/nevercall.html

Außerdem bin ich nicht sicher, dass Sie wirklich einen virtuellen Konstruktor benötigen. Sie können ohne sie polymorphen Aufbau erreichen. Sie eine Funktion schreiben können, die Ihr Objekt entsprechend den benötigten Parameter konstruieren wird

Eine virtuelle Tabelle (VTable) für jede Klasse mit einem oder mehreren ‚virtuellen Funktionen‘ gemacht. Immer wenn ein Objekt dieser Klasse erstellt wird, es enthält einen ‚virtuelle-pointer‘, die von entsprechenden vtable zu den Basispunkten. Wann immer es ein virtueller Funktionsaufruf ist, wird die V-Tabelle verwendet, um die Funktion Adresse aufzulösen.     Konstruktor kann nicht virtuell sein, denn wenn Konstruktor einer Klasse ausgeführt wird, gibt es keine V-Tabelle im Speicher vorhanden ist, bedeutet, dass keine virtuellen Zeiger noch definiert. Daher sollte der Konstruktor immer nicht virtuell.

Cant wir es einfach sagen, wie .. Wir können nicht Konstrukteuren erben. Also gibt es keinen Sinn, sie virtuell deklarieren, da die virtuellen Polymorphismus bereitstellt.

Der virtuelle Mechanismus funktioniert nur, wenn Sie eine Basis-Klasse Zeiger auf eine abgeleitete Klasse Objekt haben. Construction hat seine eigenen Regeln für die Berufung von Basisklassenkonstruktoren, grundsätzlich Basisklasse abgeleitet. Wie könnte ein virtueller Konstruktor nützlich oder genannt werden? Ich weiß nicht, was andere Sprachen zu tun, aber ich kann nicht sehen, wie ein virtueller Konstruktor nützlich sein könnte oder sogar umgesetzt. Bau muss stattgefunden haben, für den virtuellen Mechanismus keinen Sinn zu machen und den Bau muss auch stattgefunden haben, dass die V-Tabelle Strukturen wurden geschaffen haben, welche die Mechanik des polymorphen Verhalten bietet.

Es gibt einen sehr einfachen Grund:. Konstrukteurs sind effektiv statische Funktionen, und in C ++ keine statische Funktion kann virtuell sein

Wenn Sie viel Erfahrung mit C ++ haben, wissen Sie alles über den Unterschied zwischen statischen und Member-Funktionen. Statische Funktionen werden mit der Klasse verbunden ist, nicht die Objekte (Instanzen), so sehen sie nicht einen „diesen“ Zeiger. Nur Elementfunktionen können virtuell sein, weil das die verborgene Tabelle von Funktionszeigern vtable-, die ‚virtuelle‘ macht arbeits wirklich Mitglied jeden Objekt ein Daten vorhanden ist.

Nun, was ist die Aufgabe des Konstruktor? Es ist in der Namen- eine „T“ Konstruktor initialisiert T-Objekte, wie sie zugeordnet sind. Diese automatisch schließt es eine Elementfunktion zu sein! Ein Objekt hat zu existieren, bevor er einen „diesen“ Zeiger und damit eine vtable hat. Das bedeutet, dass selbst wenn die Sprache behandelt Konstrukteuren als gewöhnliche Funktionen (es nicht, zu verwandten Gründen werde ich nicht in bekommen), würden sie statische Elementfunktionen sein müssen.

Eine gute Möglichkeit, dies zu sehen ist auf den „Factory“ Mustern suchen, vor allem Fabrik Funktionen. Sie tun, was Sie wollen, und Sie werden feststellen, dass, wenn Klasse T eine Factory-Methode hat, ist es immer statisch ist. Es muss sein.

C ++ virtuellen Konstruktor ist nicht possible.For Beispiel Sie keinen Konstruktor als virtual.Try dieser Code markieren

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

Es bewirkt, dass ein error.This Code einen Konstruktor als virtuelle zu erklären versucht. Nun wollen wir versuchen zu verstehen, warum wir virtuelle Schlüsselwort verwenden. Virtuelle Schlüsselwort wird verwendet, Laufzeit-Polymorphismus bereitzustellen. Zum Beispiel versuchen, 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(); 
}

Im Haupt a=new anotherClass; weist einen Speicher für anotherClass in einem Zeiger a als Art von aClass.This erklärt verursacht sowohl den Konstruktor (In aClass und anotherClass) automatically.So nennen wir nicht brauchen, Konstruktor als virtual.Because zu markieren, wenn ein Objekt erzeugt es muss die Kette der Schöpfung (dh zuerst die Basis und dann den abgeleiteten Klassen) folgen. Aber wenn wir versuchen, ein delete a; löschen es nur um die Basis zu nennen verursacht destructor.So wir haben den destructor mit virtuellem Schlüsselwort zu handhaben. So virtueller Konstruktor ist nicht möglich, aber virtueller destructor ist .Thanks

Wenn Sie denken, logisch darüber, wie Konstrukteure arbeiten und was die Bedeutung / Nutzung einer virtuellen Funktion ist in C ++ dann werden Sie feststellen, dass ein virtueller Konstruktor wäre sinnlos in C ++. Deklarieren etwas virtuellen in C ++ bedeutet, dass es durch eine Unterklasse der aktuellen Klasse außer Kraft gesetzt werden kann, aber der Konstruktor aufgerufen wird, wenn das beanstandete erstellt wird, zu diesem Zeitpunkt kann man nicht eine Unterklasse der Klasse werden erstellen, müssen Sie sein die Klasse zu schaffen, so würde es nie eine Notwendigkeit, einen Konstruktor virtuellen zu erklären.

Und ein weiterer Grund ist, haben die Konstrukteure die gleichen Namen wie seine Klassennamen und wenn wir Konstruktor als virtuelles erklären, dann sollte es in seiner abgeleiteten Klasse mit dem gleichen Namen neu definiert werden, aber man kann den gleichen Namen von zwei nicht hat Klassen. So ist es nicht möglich, einen virtuellen Konstruktor zu haben.

  1. Wenn ein Konstruktor aufgerufen wird, obwohl es kein Objekt bis dahin geschaffen ist, wissen wir noch die Art von Objekt, das würde erstellt werden, weil die spezifischen Bauunternehmer der Klasse, zu dem das Objekt gehört bereits aufgerufen wurde.

    Virtual Schlüsselwort mit einer Funktion zugeordnet ist, bedeutet die Funktion eines bestimmten Objekttypen ist gonna genannt werden.

    Also, mein Denken sagt, dass es keine Notwendigkeit gibt, den virtuellen Konstruktor, weil bereits den gewünschten Konstruktor, deren Aufgabe machen würde erstellt werden soll, aufgerufen wurde und macht Konstruktor virtuell ist nur eine redundante Sache, weil der zu tun objekt- spezifische Bauunternehmer wird bereits aufgerufen worden, und dies ist die gleiche wie der Aufruf von klassenspezifische Funktion , die durch das Schlüsselwort virtual erreicht wird.

    Auch wenn die innere Implementierung nicht virtuellen Konstruktor für vptr und VTable Ähnliche Gründe erlauben.


  1. Ein weiterer Grund ist, dass C ++ eine statisch typisierte Sprache ist, und wir müssen den Typ einer Variablen zur Compile-Zeit kennen.

    Der Compiler muss sich der Klassentyp sein, das Objekt zu erstellen. Der Typ des Objekts erstellt werden soll, eine Kompilierung-Entscheidung.

    Wenn wir den Konstruktor virtuelle machen, dann bedeutet es, dass wir nicht brauchen, den Typen des Objekts zur Compile-Zeit zu wissen (das ist, was virtuelle Funktion zur Verfügung stellen. Wir brauchen nicht das eigentliche Objekt kennen und braucht nur die Basiszeiger ein tatsächliches Objekt rufen sie die spitzen Gegenstand die virtuelle Funktionen, ohne zu wissen, die Art des Objekts) zu zeigen und wenn wir die Art des Objekts bei der Kompilierung nicht wissen, dann ist es gegen die statisch typisierten Sprachen. Und daher, Laufzeit Polymorphismus kann nicht erreicht werden.

    Daher Constructor nicht ohne zu wissen, die Art des Objekts zum Zeitpunkt der Kompilierung aufgerufen werden. Und so ist die Idee, einen virtuellen Konstruktor machen ausfällt.

Die Vpointer werden zum Zeitpunkt der Objekterstellung erstellt. vpointer existiert gewohnt vor der Objekterstellung. so gibt es keinen Punkt den Konstruktor als virtuelle machen.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top