Frage

Ich möchte eine rein virtuelle Elternklasse ein Kind Implementierung einer Funktion aufzurufen, etwa so:

class parent
{
  public:
    void Read() { //read stuff }
    virtual void Process() = 0;
    parent() 
    {
        Read();
        Process();
    }
}
class child : public parent
{
  public:
    virtual void Process() { //process stuff }
    child() : parent() { }
}

int main()
{
   child c;
}

Das sollte funktionieren, aber ich erhalte einen nicht verknüpfte Fehler: / Dies ist mit VC ++ 2k3

Oder sollte es nicht funktionieren, bin ich falsch?

War es hilfreich?

Lösung

Andere Tipps

Alternativ eine Factory-Methode machen, um die Objekte zu schaffen und die Konstrukteure privat macht, kann die Factory-Methode dann das Objekt nach dem Bau initialisieren.

Wird im Allgemeinen arbeiten, aber nicht für Anrufe innerhalb der Konstruktor der rein virtuellen Basisklasse. Zu der Zeit, in konstruierte die Basisklasse, die Unterklasse außer Kraft setzt nicht existiert, so kann man es nicht nennen. Solange Sie es nennen, wenn das gesamte Objekt aufgebaut ist, sollte es funktionieren.

Es ist, weil Ihr Anruf im Konstruktor ist. Die abgeleitete Klasse wird nicht gültig sein, bis der Konstruktor, so dass Sie Compiler Sie hierfür in dinging ist richtig abgeschlossen hat.

Es gibt zwei Lösungen:

  1. Stellen Sie den Anruf zu Process () in der abgeleiteten Klasse Konstruktor
  2. definieren einen leeren Funktionskörper für Verfahren, wie in dem folgenden Beispiel:
class parent
{
  public:
    void Read() { //read stuff }
    virtual void Process() { }
    parent() 
    {
        Read();
        Process();
    }
}

Mit einem Schritt mehr Sie könnten nur eine Art von Funktion einführen wie

class parent
{
    public:
        void initialize() {
            read();
            process();
        }
}

Sie müssen innerhalb eines Objekts wickeln, dass die virtuellen Methode aufruft, nachdem das Objekt vollständig aufgebaut ist:

class parent
{
  public:
    void Read() { /*read stuff*/ }
    virtual void Process() = 0;
    parent()
    {
        Read();
    }
};

class child: public parent
{
  public:
    virtual void Process() { /*process stuff*/ }
    child() : parent() { }
};

template<typename T>
class Processor
{
    public:
        Processor()
            :processorObj() // Pass on any args here
        {
            processorObj.Process();
        }
    private:
        T   processorObj;

};




int main()
{
   Processor<child> c;
}

Die oberflächliche Problem ist, dass Sie eine virtuelle Funktion aufrufen, die noch nicht bekannt ist (Objekte werden von Eltern auf das Kind aufgebaut, so sind auch die vtables). Ihr Compiler gewarnt Sie darüber.

Die wesentlich Problem, soweit ich sehen kann, ist, dass Sie versuchen, Funktionalität durch Vererbung wiederzuverwenden. Dies ist fast immer eine schlechte Idee. Ein Designproblem, sozusagen:)

Im Wesentlichen, versuchen Sie eine Template-Methode Muster instanziiert wird, trennen Sie die was von der , wenn : zunächst einige Daten lesen (in irgendeiner Weise), dann verarbeitet (in einige Art und Weise).

Dies wird wahrscheinlich viele bessere Arbeit mit Aggregation: Der Verarbeitungsfunktion auf die Template-Methode gibt zum richtigen Zeitpunkt aufgerufen werden. Vielleicht können Sie sogar das gleiche tun für die Read-Funktionalität.

Die Aggregation kann auf zwei Arten erfolgen:

  1. Verwenden von virtuellen Funktionen (das heißt Runtime Binding)
  2. Verwenden von Vorlagen (d Kompilierzeit Binding)

Beispiel 1: Laufzeit Bindung

class Data {};
class IReader    { public: virtual Data read()            = 0; };
class IProcessor { public: virtual void process( Data& d) = 0; };

class ReadNProcess {
public:
    ReadNProcess( IReader& reader, IProcessor processor ){
       processor.process( reader.read() );
    }
};

Beispiel 2: compiletime Bindung

template< typename Reader, typename Writer > // definitely could use concepts here :)
class ReadNProcess {
public:
     ReadNProcess( Reader& r, Processor& p ) {
         p.process( r.read() );
     }
};
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top