2017-08-10 2 views
-1

Nur nicht bekommen, wie man diesen Prototyp zu implementieren. Ich versuche, einen Container mit Objekten der Basisklasse der Worker* Iteration des Containers zu erstellen, Objekte rufen die virtuelle Methode ->work(). In Abhängigkeit von abgeleiteten Klasse auf Zeiger sollte es sein Eigen nennen außer Kraft gesetzt FunktionC++ Vererbung Casting, Eltern zu Kind und zurück

class Worker { 
public: 
    Worker(...) { ... } 
    virtual void work() { /* justWork(); */ } 
}; 

class Professional : public Worker { 
public: 
    Professional(...) { ... } 
    virtual void work() override { /* workGood(); */ } 
}; 

class Workplace { 
public: 
    void train(Worker* worker) { 
     /* need to save object properties and 
      set pointer to derived class */ 

     // *worker = Professional(worker); 
     worker = new Professional(worker); 
     /* following compiles fine, but when I call worker->work() 
      outside of this body it calls simple Worker::work() 
      when I need to call Professional::work() */ 
    } 
    void fire(Worker* worker) { 
     /* need to save object properties 
      set pointer value back to 
      Parent/Base class Worker */ 

     // *worker = Worker(worker); 
    } 
}; 

int main() 
{ 
    Workplace workplace; 
    Worker* worker = new Worker(); 

    worker->work(); // Worker::work() => justWork() 

    workplace.train(worker); 
    worker->work(); 
    // should be Professional::work() => workGood(), 
    // but it calls Worker::work() => justWork() 

    workplace.fire(worker); 
    worker->work(); // Worker::work() => justWork() 

    return 0; 
} 
+0

Sie übergeben 'Worker *' nach Wert hier: 'void train (Worker * worker) {'. Ich würde empfehlen, 'std :: unique_ptr ' zu verwenden, um sie herumzugeben. – user0042

+0

Für 'Workplace :: train' übergeben Sie den Zeiger * als Wert *. Das bedeutet, dass Sie eine * Kopie * des ursprünglichen Zeigers haben, also ändert die Zuweisung nur die Kopie, nicht das Original, das Sie in der 'main' Funktion erstellt haben. –

+0

@Someprogrammerdude so versuchte ich: 'Workplace :: Zug (Arbeiter & Arbeiter) {Arbeiter = Professional(); } workplace.train (* worker); ' Auch kein Erfolg, mache ich immer noch falsch? –

Antwort

0

Ich kann unter 50 Rep nicht kommentieren, also muss ich eine Antwort schreiben. Vielleicht fixiert das Problem, aber Sie müssen auch den Speicherplatz in Arbeitsplatz :: Zug() und am Arbeitsplatz :: fire(), die Sie in main() zugeteilt befreien:

Worker* worker = new Worker(); 

Andernfalls werden Sie bekomme ein Speicherleck.

class Workplace { 
public: 
    void train(Worker*& worker) { 
     Worker* temp = worker; 
     /* A temporary pointer to the allocated object. */ 

     worker = new Professional(temp); 
     /* Allocating memory for new object. */ 

     delete temp; 
     /* Destroying previous object. */ 
    } 
    void fire(Worker*& worker) {    
     Worker* temp = worker;    
     worker = new Worker(temp); 
     delete temp; 
    } 
}; 

In Workplace::fire() Ihre Aufgabe würde *worker = Worker(worker); nicht funktionieren. worker würde immer noch auf den gleichen Typ zeigen (in diesem Fall: auf eine Professional). Sie benötigen außerdem einen virtuellen Destruktor in der Klasse Worker, wenn Sie einen Professional über einen Zeiger Worker* löschen möchten, um Speicherlecks zu vermeiden.

class Worker { 
public: 
    /* other member functions */ 
    virtual ~Worker() {} 
}; 
+0

aww, kann ich Zeiger, die im Haupt durch korrekte Weitergabe Parameter deklariert, anstelle von Speicherbefreiung? –

+0

Was meinst du mit _overwriting_? Vielleicht das: '* Arbeiter = Professional (Arbeiter)'? Weil es nicht funktioniert. Wenn der Zeiger auf ** einen anderen Typ ** zeigen soll, müssen Sie Speicher für das neue Objekt zuweisen und das vorherige Objekt löschen. –

+0

Außerdem ist es besser, anstelle von Zeigern Verweise auf die Konstruktoren zu übergeben: 'Professional (const Worker &)' und 'Worker (const Professional &)'. Und nenne sie so: 'worker = new Professional (* temp)' und 'worker = new Worker (* temp)'. Wenn Sie als Referenz übergeben werden, erstellen Sie keine Kopie der Zeiger. –

0

es wurde falsch Parameterübergabe, fest:

void train(Worker*& worker) { ... } 
void fire(Worker*& worker) { ... } 

Jetzt funktioniert es, tnx @Someprogrammerdude @ user0042