试图重载cout<<运营商,但它不工作

时间:2012-01-31 06:26:36

标签: c++ overloading operator-keyword

我在这里剪掉了我班上不相关的部分。我不知道我做错了什么,只是想尝试cout<<对象。

#include <iostream>

class Snipped
{

    public:
        friend std::ostream& operator<<(std::ostream& os, const Snipped& s);

    protected:
    private:
};

std::ostream& operator<<(std::ostream& os, const Snipped& s)
{
    os << "test";
    return os;
}

int main(int argc, char* argv[])
{
    Snipped* s = new Snipped();

        std::cout << s << std::endl << s;

    delete s;
    return 0;
}

预期产出:

test
test

实际输出:

0x12ae20
0x12ae20  (random memory location?)

3 个答案:

答案 0 :(得分:8)

std::cout << s << std::endl << s;      

您正在使用地址呼叫<<,您需要使用Snipped类型的对象来呼叫它。 上面的代码行不会调用重载的运算符函数,因为重载函数的参数不匹配。

您需要致电:

std::cout << *s << std::endl << *s;      

这可确保调用<<重载的操作符函数,因为参数与之匹配。

答案 1 :(得分:6)

尝试

std::cout << *s << std::endl; 

顺便说一下,

std::cout << s << std::endl; 

实际上不是随机内存位置。

在这种情况下,它是堆上的实际内存地址。

您实际上可以使用该地址来检查对象的身份。

这在调试或实际代码中很有用。 例如,如果你看一下赋值运算符,你会经常看到:

class Foo
{
  Foo& operator=( const Foo& foo )
  {
    // use the identity principle 
    if ( &foo==this )
      return *this;  // so I don't waste CPU cycles copying to myself

    // ...really do copy here
    return *this;
  }
};

答案 2 :(得分:2)

虽然只是取消引用指针(即使用'* s'而不是's'),有一条更大的鱼可以炒!除非有充分的理由将对象放在堆上,否则不应该这样做:

int main()
{
    Snipped s;
    std::cout << s << '\n' << s;
}

我发现在我编写的程序中使用new等等delete非常罕见。除了更简单的代码之外,这也很方便地产生更快的程序。如果你真的需要在堆上分配一些东西,可以使用某种智能指针来确保对象自动释放:

int main()
{
    std::unique_ptr<Snipped> s(new Snipped);
    std::cout << *s << '\n' << *s;
}

作为旁注,请不要使用std::endl,除非您真的打算刷新流:我发现不恰当地使用std::endl不止一次成为大规模性能问题的根本原因。当然,大部分时间都没关系,但在更多情况下,你不关心同花顺。如果您不喜欢使用'\n'"\n",则可以使用自定义操纵器:

std::ostream& nl(std::ostream& out) { return out << '\n'; }

使用此功能,您可以使用nl代替std::endl,并且不会总是冲洗流。