2013-07-02 11 views
5

So, basierend auf einer kursorischen Suche, weiß ich bereits, dass das Aufrufen einer virtuellen Funktion (rein oder anders) von einem Konstruktor ein Nein ist. Ich habe meinen Code neu strukturiert, um sicherzustellen, dass ich das nicht mache. Während dies verursacht, dass der Benutzer meiner Klassen einen zusätzlichen Funktionsaufruf in ihrem Code hinzufügt, ist das wirklich kein großer Deal. Anstatt nämlich den Konstruktor in einer Schleife aufzurufen, rufen sie jetzt die Funktion auf, die (tatsächlich!) Die Leistung des Codes erhöht, da wir nicht jedes Mal die Aufgabe haben, das betreffende Objekt zu erstellen und zu zerstören.Aufruf der reinen virtuellen Funktion von der abstrakten Basisklassenmitgliedsfunktion?

Allerdings habe ich etwas Interessantes ... gestolpert

In der abstrakten Klasse habe ich so etwas wie dieses:

// in AbstractClass.h: 
class AbstractClass { 
public: 
    AbstractClass() {} 
    virtual int Func(); //user can override 
protected: 
    // Func broken up, derived class must define these 
    virtual int Step1() = 0; 
    virtual int Step2() = 0; 
    virtual int Step3() = 0; 
// in AbstractClass.cpp: 
int AbstractClass::Func() { 
    Step1(); 
    // Error checking goes here 
    Step2(); 
    // More error checking... 
    // etc... 
} 

Grundsätzlich gibt eine gemeinsame Struktur, die die reinen virtuellen Funktionen folgen die meisten der Zeit, aber wenn sie nicht Func() ist virtuell und ermöglicht der abgeleiteten Klasse, die Reihenfolge anzugeben. Jeder Schritt muss jedoch in abgeleiteten Klassen implementiert werden.

Ich wollte nur sicher sein, dass ich hier nichts falsch mache, da die Func() - Funktion die rein virtuellen aufruft. Das heißt, wenn Sie die Basisklasse aufrufen, treten bei einem Aufruf von StepX() schlimme Dinge auf. Die Klasse wird jedoch verwendet, indem ein abgeleitetes Objekt erstellt wird und anschließend Func() (z. B. MyDerivedObject.Func();) für dieses abgeleitete Objekt aufgerufen wird, wobei alle reinen virtuellen Funktionen ordnungsgemäß überladen haben sollten.

Gibt es etwas, das ich vermisse oder falsch mache, wenn ich diese Methode befolge? Danke für die Hilfe!

+1

Dies ist ein Lehrbuchbeispiel für die Verwendung des [Non-Virtual Interface idiom] (http://en.wikipedia.org/wiki/Non-virtual_interface_pattern) zur Implementierung des [Template Method pattern] (http: // en. wikipedia.org/wiki/Template_pattern). – Casey

+0

Zur Klarstellung, es gibt einen großen Unterschied zwischen "Aufruf von virtuellen Funktionen in einem Konstruktor" und "Aufruf von rein virtuellen Funktionen". Ersteres ist schwierig und entmutigt (obwohl gültig), letzteres ist völlig falsch (und auch nicht ganz trivial). –

+0

Das Aufrufen einer virtuellen Funktion in einem Konstruktor oder Destruktor ist kein "Nein", es sei denn, Sie haben sich nicht die Mühe gemacht zu verstehen, wie sie funktionieren. –

Antwort

4

Func ruft die virtuellen an, nicht die reinen virtuellen. Sie müssten die Aufrufe mit einem Bereichsoperator qualifizieren, d. H. AbstractClass :: Step1(), um die THAT-Funktion (virtual pure) aufzurufen. Da Sie nicht sind, erhalten Sie immer eine Implementierung von einer abgeleiteten Klasse.

+0

Also egal was ich tue, außer wenn ich etwas wirklich hacky wie AbstractClass :: Step3() mache, werden die Funktionen von der abgeleiteten Klasse überschrieben? Gibt es bei diesem Ansatz irgendwelche roten Fahnen in Bezug auf gute C++ - Code-Praktiken? –

+3

Eigentlich macht es OO und C++ mächtig. Sie können "Prozeduren" schreiben, in denen die abgeleitete Klasse die Details angeben kann. Denken Sie an ein Kommunikationsprotokoll. EstablishConnection(); während(!Fertig()) {SendRequest(); GetResponse();} TerminateConnection(); Alle diese Methoden können "virtuell" sein, eine abgeleitete Klasse verwendet TCP, eine andere verwendet sogar einen höheren "Verbindungs" -Mechanismus oder ein einfacheres Punkt-zu-Punkt-RS-232-Protokoll hat nichts in ihren Establish/TerminateSession() - Methoden. Sie haben jedoch ein kleines Framework definiert, das einfach implementiert und erweitert werden kann. – franji1

+0

Danke für die Erklärung. Ich bin ziemlich neu in einigen dieser OO Konzepte und ich möchte so scharf wie möglich sein ... –

1

Eine virtuelle Funktion in einer Basisklasse bewirkt, dass die abgeleiteten Klassen diese überschreiben können. Aber es scheint, dass die Dinge dort aufhören.

Wenn die virtuelle Funktion der Basisklasse jedoch rein ist, erzwingt dies die abgeleiteten Klassen zur Implementierung der Funktion.

-1

Als Nebenkommentar können Sie die Step1-, Step2-, Step3-Methoden privat machen, so dass Sie vom Compiler nicht direkt aufgerufen werden können.

+1

Sollte ein Kommentar sein? – lpapp

Verwandte Themen