今天被操作符“<<”和“>>”的重载问题给纠缠一天,终于给搞懂了些。这一天的成果如果不来总结总结真的是对不起我的时间了。
今天突然想自己实现下标准库 string 的部分功能,如构造,析构,输入,输出等。定义的类名为MyString。在实现“<<”操作符的重载时,遇到了很多问题让我,如下:
(1)在未查资料的情况下,部分代码如下:
//file name: MyString.h
#include <iostream>
using std::cout;
using std::endl;
class MyString {
private:
char *str;
public:
MyString &operator <<(MyString s);
};
//file name: MyString.cpp
#include "MyString.h"
MyString& MyString::operator<< (MyString s)
{
cout<<s.str;
return *this;
}
//file name: MainTest.cpp
#include "MyString.h"
int main(int argc, const char* argv[])
{
MyString ms1= "hello world";
cout<<ms1;<span style="white-space:pre"> </span>//这句显示错误<span style="color: rgb(255, 0, 0); "><strong>
</strong></span> return 0;
}
结果出现错误:
error C2679: binary '<<' : no operator defined which takes a right-hand operand of type 'class MyString' (or there is no acceptable conversion)
出现错误的语句在上面标红的句子上。想不明白原因,于是查了资料:有的说没有引入 iostream ; 有的说要 operator<< 函数参数要加上 & 符号,即:MyString& operator<< (MyString &s)。 于是都照做了。结果:失败!还是error C2679。先说下自己困惑的地方:
在这里 operator<< 是类 MyString 的成员函数,而cout<<ms1 中调用这应该是 cout ,这明显不对。如果不用 cout 输出那要怎样输出了。于是乎,既然是类MyString 的成员函数,那就让ms1调用,然后传入又把参数ms1传入(这样写的话,明显是垃圾代码)。出乎意料的是,修改后竟然不报错了。
修改后语句1:
ms1<<ms1;
运行程序
修改后语句2:
ms1<<ms1<<endl; //ms1<<ms1<<"\n"; 不报错
结果又出现了同样的错误。这完全不符合自己想要的结果,显然这样重载肯定是有问题的。于是继续查资料。。。
。。。。。
发现,说"<<"的重载一般都用友元函数来重载,原因是前面所说的,调用者是cout,cout不是 MyString 的对象,无法调用其成员函数。这下好了,这样只要把成员函数改为友元函数就行了。于是修改代码:
//file name: MyString.h
friend std::ofstream& operator<< (std::ofstream &os, const MyString &s);<span style="white-space:pre"> </span>//注意ofstream
//file name: MyString.cpp
std::ofstream& operator<< (std::ofstream &os, const MyString &s)
{
cout<<s.str;
return os;
}
// file name: MainTest.cpp
#include "MyString.h"
int main(int argc, const char* argv[])
{
MyString ms1= "hello world";
cout<<ms1<<endl;
return 0;
}
结果:编译错误!!!
还是error C2679: binary '<<' : no operator defined which takes a right-hand operand of type 'class MyString' (or there is no acceptable conversion)
我崩溃了。。。检查代码好久好久,竟然坑爹的发现自己犯了低级错误,把 ostream 写成了 ofstream。 于是把代码替换了。
结果:成功了!!!
下面进行重要的小结哈。。。。
1. 重要的一点, error C2679: binary '<<' :...,并不是网上有的说的加入头文件 iostream 或是 参数加 & 符号就一定能解决的。这个错误是告诉我们 "<<" 操作符无法操作类 MyString 的对象。这说明什么? 说明上面两种情况都没有成功的对 "<<" 进行重载(第一种情况勉强可以吧,虽然觉得是没用的代码)。So, 以后遇到这错误,应该能很快的发现错误根源了。C2679我记住你了。
2. 既然用了友元函数,operator<<可以看做是函数名,cout<<ms1; 是把cout当做参数1,ms1作为参数2传给了 operator<< 函数,那就可以显示的调用 operator<<函数,如:operator<<(cout, ms1);
3. 要可以连续输出,则返回类型就应该为 std::ostream&
以上是今天的小小收获,能力有限,有错的地方希望大家指出哈。。。