2010-06-28 2 views
5

Hier ist, was ich versuche zu tun (dieser Code nicht funktioniert):Wie kann eine abgeleitete C++ - Klasse sich selbst über einen Basiszeiger klonen?

class Base 
{ 
    virtual Base *clone() { return new Base(this); } 
    virtual void ID() { printf("BASE"); 
}; 

class Derived : publc Base 
{ 
    virtual Base *clone() { return new Derived(this); } 
    virtual void ID() { printf("DERIVED"); } 
} 

. 
. 
Derived d; 
Base *bp = &d; 
Base *bp2 = bp->clone(); 

bp2->ID(); 

Was ich wie ist ausgedruckt, um zu sehen „Abgeleitet“ ... was ich bekommen ist „BASE ". Ich bin ein langjähriger C-Programmierer und ziemlich erfahren mit C++ ... aber ich komme mit diesem hier nicht voran ... jede Hilfe wäre willkommen.

+0

Zeige mehr Code, speziell alle Konstruktoren jeder Klasse in diesem Fall ist wichtig. (Einige können aus Ihrem Code abgeleitet werden, aber es hilft bei der Suche nach mehr richtigen Antworten von allen ...) – Macke

+0

Hm. Der ursprüngliche Code hatte Base bp = & d. Jetzt wurde es geändert in Base * bp = & d; – Macke

+0

Nicht relevant für die Frage, aber Sie wollen auch virtuelle Destruktoren für die Klassen. –

Antwort

0

Sie sind slicing die Klasse in Base bp = &d; (diese konstruiert eine neue Basis bp von der abgeleiteten ptr.)

Base* bp = &d; stattdessen versuchen. (Dh einen Zeiger der Basistyp des abgeleiteten Objekts erstellen.)

+1

Ich sehe keine Edit-Anweisung auf dem OP (zu diesem Zeitpunkt), und der Code macht bereits, wie Sie vorschlagen (obwohl es überhaupt nicht kompiliert). Während das gemeldete Problem sicherlich nach einem Slicing-Problem riecht, zeigt der gepostete Code es nicht ... Edit: Hoppla, ich habe den falschen Beitrag für die Editiermarke gesucht. Du hast recht, Marcus. Entschuldigen Sie die Umstände. –

1

Mit Base bp = &d;

Sie haben d „geschnitten“, so an den Compiler, bp wirklich nur vom Typ Base, weshalb, wenn Sie Call bp->clone() der Compiler ruft Base::clone(); und bp2->ID() Drucke BASE.

Base& bp = d; wird tun, was Sie wollen.

0

Ihr Beispiel ist falsch und wird nicht kompiliert. Insbesondere diese Zeile:

Base bp = &d; 

, die auch die Ursache des Problems sein können (Sie können Ihre Aufgabe sein Slicing), aber ich kann nicht mit Sicherheit sagen, ohne zu arbeiten Code zu sehen.

Sie haben auch ein Problem, wo Ihre beiden Klassen nicht verwandt sind (hätten meinen Sie class Derived : public Base zu schreiben?)

+0

Ja, ich weiß, dass dieser Code nicht kompiliert wird. Ich habe diesen Fehler innerhalb einer Minute behoben, aber ihr seid schnell! Bitte lesen Sie die korrigierte Frage. Ich weiß nicht, was "Slicing" ist, aber ich bin auf der Suche ... – wanlessv

+1

@wanlessv - Sie sollten immer sicherstellen, dass Ihr Code kompiliert, bevor Sie eine Frage stellen. Ohne genau zu wissen, was Sie zu tun versuchen, können wir nicht immer sehen, was das Problem ist. –

3

Dieser Code ist mit syntaktischen Fehlern gespickt. Vielleicht am wichtigsten ist, dass Derived nicht von Base erbt. Zweitens benötigt Base neben den syntaktischen Fehlern (vermutlich einfache Tippfehler) offensichtlich einen virtuellen Destruktor. Die Clone-Methode verlangt ziemlich genau, dass Sie den Operator delete auf einem Basiszeiger (Base *) aufrufen können.

class Base 
{ 
public: 
    virtual ~Base() {} 
    virtual Base* clone() const { return new Base(*this); } 
    virtual void ID() const { printf("BASE"); } 
}; 

class Derived: public Base 
{ 
public: 
    // [Edit] Changed return type to Derived* instead of Base*. 
    // Thanks to Matthieu for pointing this out. @see comments below. 
    virtual Derived* clone() const { return new Derived(*this); } 
    virtual void ID() const { printf("DERIVED"); } 
}; 

int main() 
{ 
    Derived d; 
    Base* bp = &d; 

    Base* bp2 = bp->clone(); 
    bp2->ID(); // outputs DERIVED as expected 
    delete bp2; 
} 
+1

Ich entschuldige mich bei allen ... Ich habe ein einfaches Beispiel erstellt und gepostet, wobei ich versucht habe, jeden im eigentlichen Code zu begraben ... aber ich habe mehrere Fehler in der einfachen Version gemacht, und bevor ich zurückkommen und sie korrigieren konnte, habe ich hatte mehrere Antworten! An dieser Stelle weiß ich nicht, welche der Antworten mein Buggy-Beispiel beantworten, die noch zu meiner eigentlichen Frage gehören ... – wanlessv

+0

Es ist auch besser, einen Smart Pointer (zB boost :: shared_ptr) zu verwenden lösche automatisch bp2. –

+0

@Daniel Ja, aber ich denke, wenn das OP Schwierigkeiten mit Vererbung und Polymorphismus hat, kann es eine Weile dauern, bis er RAII und Smart Pointer verstehen kann. – stinky472

7

Sobald alle Kompilierung Fehler behoben sind, hatte ich am Ende auf den Punkt:

#include <cstdio> 

class Base 
{ 
    public: 
    Base() {} 
    Base(const Base&) {} 
    virtual Base *clone() { return new Base(*this); } 
    virtual void ID() { printf("BASE"); } 
}; 

class Derived : public Base 
{ 
    public: 
    Derived() {} 
    Derived(const Derived&) {} 
    virtual Base *clone() { return new Derived(*this); } 
    virtual void ID() { printf("DERIVED"); } 
}; 


int main() 
{ 
    Derived d; 
    Base *bp = &d; 
    Base *bp2 = bp->clone(); 

    bp2->ID(); 
} 

Was gibt Ihnen, was Sie suchen, - STAMM.

+0

Danke euch allen für eure Zeit. Bei diesem Beispiel denke ich, dass ich das Problem verstehe. – wanlessv

0

Der Code sieht gut aus, abgesehen von den dummen Syntax-Tippfehlern und den fehlenden Codes.

Verwandte Themen