我们在写自己定义类型时往往需要重载双目运算符,比如自己实现String类型,如果你希望使用cout<<输出String类型,就需要重载<<运算符,你可能会这么写重载:
class String
{
private:
char* str;
int length;
public:
String(const String& strO)
{
length = strlen(strO.str);
str = new char[length + 1];
strcpy_s(str, length + 1, strO.str);
}
String(const char* c)
{
if (c == NULL)
{
str = new char[1];
*str = '\0';
length = 0;
}
else
{
length = strlen(c);
str = new char[length + 1];
strcpy_s(str, length + 1, c);
}
}
String& operator = (const String& strO)
{
if (this == &strO)
{
return *this;
}
delete[] str;
length = strlen(strO.str);
str = new char[length + 1];
strcpy_s(str, length + 1, strO.str);
return *this;
}
std::ostream& operator<< (std::ostream& os, const String strO)
{
os << strO.str;
return os;
}
~String()
{
delete[] str;
}
};
如果你把<<操作符重载放在类里面重载,那么会报错“此运算符参数太多”,以为类的普通函数会默认又一个this指针入参,而双目运算符只有两个入参,按照上面的写法加上this参数就有了三个参数,所以报错。你可能会改成这样,仍然在类里面定义,但是把String参数去掉:
std::ostream& operator<< (std::ostream& os)
{
os << this->str;
return os;
}
这样确实类定义不会报错了,但是当你使用cout<<输出String对象时就报错:
进制“<<”: 没有找到接受“String”类型的右操作数的运算符(或没有可接受的转换) 。
这是因为省略的this参数默认是在操作符的左边,也就是重载的<<操作符使用是这样的”this << cout“的,如果你重载的是<、>、==、!=等比较的双目运算符,可以这么写,但是重载流输出运算符<<却不能这样写。正确的写法是把重载<<的函数放在类的外面,当作一个全局的函数重载(不需要String::指明它是String类的),代码如下:
class String
{
//省略
friend std::ostream& operator<< (std::ostream& os, const String strO);
}
std::ostream& operator<< (std::ostream& os, const String strO)
{
os << strO.str;
return os;
}
这样就能正常使用cout<<输出String对象了。声明为friend是为了能够访问私有成员str。