如何从基类调用重载函数(不是抽象的)?

时间:2012-04-05 10:11:02

标签: c++

类DVD继承类Media,比基类多一个变量。

我声明了一个指针:

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

我想打印出DVD的内容,因此以下代码按预期工作:

ptr->print(cout);

但是使用重载的<< operator只调用基类print()函数:

cout << *ptr << endl;

因此它只打印出ID,而不是导演的名字。

解决此问题的一种方法是修改重载&lt;&lt;运算符有点让它接受指针,所以:

cout << ptr << endl;

应该可行,但不知怎的,我必须找到让cout << *ptr << endl;按预期工作的方法。

有什么建议吗?

问题是我不能使基类(Media)抽象化,因为我需要在重载ostream运算符中调用它的实例,所以基类的指针不能调用它的重载函数衍生类,它指向的。

代码:

#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!
} 

2 个答案:

答案 0 :(得分:1)

或通过参考Media&amp; amp;到&lt;&lt;这样就可以进行虚拟调度。

您正在直接传递Media对象,这意味着将创建DVD对象的新副本,并且仅丢弃DVD部分,并且只有它的Media部分将以aMedia参数结束。

请参阅:

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

答案 1 :(得分:1)

问题在于此声明ostream& operator << (ostream& out, Media aMedia)。您通过副本接受参数aMedia导致对象切片,通过将签名更改为ostream& operator << (ostream& out, const Media& aMedia)来使用引用接受它。

由于您执行cout << *ptr时的切片,DVD副本创建的类型为Media(即DVD被切片为媒体) ,现在当您调用print时,因为对象的类型为Media,调用将转到Media::print。您可以阅读有关对象切片here的更多信息。