错误<<运算符重载返回一个std ::字符串

错误<<运算符重载返回一个std ::字符串

问题描述:

如果<<运算符超载的返回类型为std::string,我很难理解编译器控制错误的原因。你能帮我理解吗?错误<<运算符重载返回一个std ::字符串

波纹管是一个可重现的例子,它给出了一个巨大的错误。

class XY 
{ 
    int X__; 
    int Y__; 
public: 
    XY(int x, int y):X__(x), Y__(y){} 
    ~XY(){} 

    std::string operator<<(const XY_cartesiano& c) 
    { 
     std::stringstream ss; 
     ss << "{ " << X__ << ", " << Y__ << " }"; 
     return ss.str(); 
    } 

    int x() const{return X__;} 
    int y() const{return Y__;} 
}; 

void main() 
{ 

XY a(1,2); 
std::cout << a; 
} 
+1

这是没有问题的,但包含两个连续的下划线('X__','Y__')和名称的名称以下划线跟着一个大写字母开头保留供实施使用。不要在你的代码中使用它们。 –

让我们这样的事情作为一个例子:

cout << "My number is " << 137 << " and I like it a lot." << endl; 

这被分析为

((((cout << "My number is ") << 137) << " and I like it a lot.") << endl); 

尤其注意到表达cout << "My number is "必须评估的东西,这样,当然后我们尝试插入137与<< 137的含义是“请137并将其发送到cout”。

想象一下,如果cout << "My number is "要返回string。在这种情况下,<< 137位会尝试在左侧的string与右侧的int之间使用<<运算符,这在C++中没有很好定义。

约定是让流插入运算符operator <<返回对左侧流的引用,以便这些操作链接良好。这样,<< 137左侧的东西本身就是cout,所以上面的代码基本上是一系列链接调用来插入cout。因此,这些功能的签名通常如下所示:

ostream& operator<< (ostream& out, const ObjectType& myObject) { 
    // ... do something to insert myObject into out ... // 
    return out; 
} 

现在,一切正常链接。注意这个函数是一个自由函数,不是成员函数,左边是ostream类型,右边有你的类的类型。这是做这件事的传统方法,因为如果你尝试将operator <<作为成员函数进行重载,那么左边将是你类类型的操作数,这与流插入应该如何工作相反。如果您需要专门访问类的私有领域在实现此功能的过程中,使之成为朋友:

class XY { 
public: 
     ... 
     friend ostream& operator<< (ostream& out, const XY& myXY); 
}; 

ostream& operator<< (ostream& out, const XY &myXY) { 
    ... 
    return out; 
} 

正确方法重载<<运营商,你的情况是

ostream& operator<<(ostream& os, const XY& c) 
{ 
    os << c.X__ <<" "<< c.Y__ ; 
    return os; 
} 
+0

实际上,如果'os'设置了其宽度修饰符(或其他瞬态流修饰符),以便输出不会部分损坏,那么使用内部'ostringstream'可以构建一次打印的整个字符串。 – templatetypedef

你有重载operator<<的方式与当您打算将对象(如std::cout)使用该操作符时必须遵循的约定不符。

事实上,您的operator<<的签名与流无关!它只是XY的成员函数,它需要另一个XY(它不使用它),返回一个字符串并具有一个非名称。这里是你如何在理论上称之为:

XY a(1,2); 
XY b(1,2); 
std::string x = (a << b); 

超载operator<<为使用流,正确的方法是使运营商在非成员函数中,添加一个流的参考参数和返回流参照流参数。你也不需要字符串流;你直接写入到流你:

#include <iostream> 

class XY 
{ 
    int x; 
    int y; 
public: 
    XY(int x, int y) : x(x), y(y) {} 

    int X() const { return x; } 
    int Y() const { return y; } 
}; 

std::ostream& operator<<(std::ostream& os, XY const& c) 
{ 
    os << "{ " << c.X() << ", " << c.Y() << " }"; 
    return os; 
} 

int main() 
{ 
    XY a(1,2); 
    std::cout << a; 
}