使用运算符打印派生对象<<超载不工作

时间:2014-06-15 17:17:55

标签: c++ polymorphism operator-overloading

为什么我不能使用这种方法打印派生对象?如何解决此问题,以便派生的打印输出打印"派生尺寸= 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;
}

3 个答案:

答案 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()的虚拟调用。

ideone