3

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

我声明一个指针:

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

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

ptr->print(cout);

但是使用重载的 << 运算符只会调用基类 print() 函数:

cout << *ptr << endl;

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

解决此问题的一种方法是稍微修改重载 << 运算符以使其接受指针,因此:

cout << ptr << endl;

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

有什么建议吗?

问题是我不能使基类(媒体)抽象,因为我需要在重载 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!
} 
4

2 回答 2

1

或者通过引用 Media& 将 aMedia 传递给 << 以便进行虚拟调度。

您正在直接传递一个 Media 对象,这意味着将创建 DVD 对象的一个​​新副本,并且仅 DVD 的部分将被丢弃,只有它的 Media 部分最终会出现在 aMedia 参数中。

看:

ostream& operator << (ostream& out, const Media& aMedia){
    aMedia.print(out);
    return out;
}
于 2012-04-05T10:14:39.680 回答
1

问题出在这个声明ostream& operator << (ostream& out, Media aMedia)中。您aMedia通过复制接受导致对象切片的参数,通过将签名更改为ostream& operator << (ostream& out, const Media& aMedia).

因为你做的切片cout << *ptr,一个类型的副本DVD被创建Media(即 DVD 被切片到一个媒体),现在当你调用时,print因为对象的类型是Mediacall 转到Media::print. 您可以在此处阅读有关对象切片的更多信息。

于 2012-04-05T10:15:08.383 回答