为什么我不能使用这种方法打印派生对象?如何解决此问题,以便派生的打印输出打印"派生尺寸= 8"。理想情况下,我希望将打印代码保留在类代码之外。
#include <iostream>
class base
{
public:
base(int size) : size_(size) {}
virtual int get_size() const { return size_; }
private:
int size_;
};
std::ostream& operator<<(std::ostream& os, const base& obj) {
os << "base size=" << obj.get_size() << std::endl;
return os;
}
class derived1 : public base
{
public:
derived1(int size) : base(size) {}
virtual int get_size() const {
return 2 * base::get_size();
}
};
std::ostream& operator<<(std::ostream& os, const derived1& obj) {
os << "derived1 size=" << obj.get_size() << std::endl;
return os;
}
int main(int argc, char* argv[]) {
base* b1 = new base(3);
std::cout << "b1 size is: " << b1->get_size() << std::endl;
std::cout << *b1 << std::endl;
base* b2 = new derived1(4);
std::cout << "b2 size is: " << b2->get_size() << std::endl;
std::cout << *b2 << std::endl;
delete b1;
delete b2;
return 0;
}
Output:
b1 size is: 3
base size=3
b2 size is: 8
base size=8
更新:
我根据ghostsofstandardspast改变如下:
#include <iostream>
class base
{
public:
base(int size) : size_(size) {}
virtual int get_size() const { return size_; }
friend std::ostream& operator<<(std::ostream &os, const base& obj);
private:
virtual std::ostream &print(std::ostream &os) const {
return os << "base size=" << get_size() << std::endl;
}
int size_;
};
std::ostream& operator<<(std::ostream& os, const base& obj) {
obj.print(os);
return os;
}
class derived1 : public base
{
public:
derived1(int size) : base(size) {}
virtual int get_size() const {
return 2 * base::get_size();
}
friend std::ostream& operator<<(std::ostream &os, const derived1& obj);
private:
virtual std::ostream &print(std::ostream &os) const {
return os << "derived1 size=" << get_size() << std::endl;
}
};
int main(int argc, char* argv[]) {
base* b1 = new base(3);
std::cout << "b1 size is: " << b1->get_size() << std::endl;
std::cout << *b1 << std::endl;
base* b2 = new derived1(4);
std::cout << "b2 size is: " << b2->get_size() << std::endl;
std::cout << *b2 << std::endl;
return 0;
}
答案 0 :(得分:1)
operator<<
不是虚拟成员函数,因此不能像其他成员函数那样以多态方式使用它。相反,您应该委托给虚拟成员。
将operator<<
重载更改为名为print
的虚拟成员函数或类似内容。然后,重载operator<<
以委托:
std::ostream &operator<<(std::ostream &os, const Base &obj) {
obj.print(os); //or whatever name you choose
return os;
}
如果您想将会员功能设为私有,请将operator<<
设为好友。
最后,请注意,打印指向类对象的指针只会打印地址。要调用operator<<
,您需要打印对象本身:
Base *b = /*whatever*/;
std::cout << *b;
this cppquiz question演示了多态operator<<
的这种技巧。我强烈建议你回答这些问题。
答案 1 :(得分:0)
cout << b2
没有调用您的运算符&lt;&lt;,因为b2
是指针而不是引用。请改为cout << *b2
。
答案 2 :(得分:0)
它无效,因为在通话中
std::cout << b1 << std::endl;
您正在打印一个地址,因为b1
是一个指针(即0x8e02008)。
你应该取消引用它
std::cout << *b1 << std::endl;
在这种情况下,对于*b1
和*b2
个对象,std::ostream& operator<<(std::ostream& os, const base& obj);
将成为calles,并且将执行对get_size()
的虚拟调用。