2012-04-05 13 views
3

Klasse DVD erbt Klasse Media, hat eine weitere Variable als die Basisklasse.So rufen Sie Überladungsfunktionen aus der Basisklasse auf (nicht abstrakt)?

Ich erkläre einen Zeiger:

Media* ptr = new DVD(...); 

Ich möchte aus dem Inhalt der DVD drucken, so dass der folgende Code funktioniert wie erwartet: nur

ptr->print(cout); 

Aber mit den überladenen < < Betreiber ruft die print() - Funktion der Basisklasse auf:

cout << *ptr << endl; 

Es druckt also nur die ID aus, nicht den Namen des Regisseurs.

Eine Möglichkeit, dieses Problem zu lösen, ist die Überlastung < < Bediener ein wenig zu ändern, um es Zeiger zu machen zu akzeptieren, so:

cout << ptr << endl; 

sollte funktionieren, aber irgendwie muss ich den Weg finden cout << *ptr << endl; Arbeit zu machen erwartet.

Irgendwelche Ratschläge?

Die Sache ist, ich kann die Basisklasse (Media) nicht abstrakt machen, weil ich eine Instanz davon im überladenen ostream -Operator aufrufen muss, damit ein Zeiger der Basisklasse die Überladungsfunktion des Abgeleiteten nicht aufrufen kann Klasse, auf die es zeigt.

Code:

#include <iostream> 
using namespace std; 

class Media{ 
    private: 
     int id; 
    public: 
     Media(int _id) : id(_id) {} 
     virtual ~Media(); 
     virtual void print(ostream &out); 
     friend ostream& operator << (ostream& out, Media aMedia); 
}; 
Media::~Media(){} 

class DVD : public Media { 
    private: 
     string director; 
    public: 
     DVD(int _id, string _director = "unknown") : Media(_id), director(_director) {} 
     ~DVD(); 
     void print(ostream &out); 
}; 
DVD::~DVD(){} 

void Media::print(ostream& out){ 
    out << "ID " << id; 
} 
void DVD::print(ostream& out){ 
    out << "DVD: "; 
    Media::print(out); 
    out << " Directed by " << director; 
} 
ostream& operator << (ostream& out, Media aMedia){ 
    aMedia.print(out); 
    return out; 
} 

int main() { 
    Media *ptr = new DVD(352, "Stephen Spielberg"); 
    ptr->print(cout); // Prints out: "DVD: ID 352 Directed by Stephen Spielberg". Correct! 
    cout << endl; 
    cout << *ptr << endl; //Prints out: "ID 352" Incorrect! 
} 

Antwort

1

Problem ist in dieser Erklärung ostream& operator << (ostream& out, Media aMedia). Sie akzeptieren den Parameter aMedia durch Kopieren, der das Objekt-Slicing verursacht, akzeptieren Sie es, indem Sie eine Referenz verwenden, indem Sie die Signatur in ostream& operator << (ostream& out, const Media& aMedia) ändern.

Wegen der Scheibe, wenn Sie cout << *ptr tun, ein kopieren des DVD des Typs erstellt wird Media (dh DVD ist mit einem Medien in Scheiben geschnitten), jetzt, wenn Sie print nennen, da die Art des Objekts ist Media Anruf geht zum Media::print. Sie können mehr über Objekt-Slicing lesen here.

+0

Alles gut, ich hatte nie klar verstanden, warum sollten wir const Referenz in Überladungsfunktionen verwenden, anstatt nur die Variable selbst zu verwenden, aber alles klar jetzt. Vielen Dank! –

1

Oder passieren aMedia durch Verweis Medien & zu < < so dass virtuelle Dispatching auftreten.

Sie übergeben ein Media-Objekt direkt, was bedeutet, dass eine neue Kopie des DVD-Objekts erstellt wird, und nur die DVD-Teile werden verworfen und nur die Media-Teile davon werden im aMedia-Parameter landen .

sehen:

ostream& operator << (ostream& out, const Media& aMedia){ 
    aMedia.print(out); 
    return out; 
} 
+1

Besser machen Sie eine const Referenz. – Henrik

+0

guter Punkt, getan –

+0

Alles gut, ich hatte nie klar verstanden, warum sollten wir const Referenz in Überladungsfunktionen verwenden, anstatt nur die Variable selbst zu verwenden, aber alles klar jetzt. Danke! –

Verwandte Themen