整理日: 2015年03月18日ios
在 C++ 中,操做符(运算符)能够被重载以改写其实际操做。同时咱们能够定义一个函数为类的朋友函数(friend function)以便使得这个函数可以访问类的私有成员,这个定义一般在头文件中完成。c++
在Visual C++中定义通常的函数为朋友函数一般是没有问题的。然而对某些重载操做符的函数,即便咱们将它们定义为类的朋友函数,VC的编译器仍然会显示出错信息,认为这些朋友函数无权访问类的私有成员。我认为这应该是VC6.0的bug。函数
如下代码就是个例子:spa
// 头文件 "Sample.h" #include<iostream> using namespace std; class Sample { public: Sample(); friend ostream &operator<<(ostream &out, const Sample s); friend istream &operator>>(istream &in, Sample & s); private: int x; }; // 实现文件 "Sample.cpp" #include "Sample.h" Sample::Sample() { x=0; } istream &operator>>(istream &in, Sample & s) { cout<<"Please enter a value"<<endl; in >> s.x ; return in; } ostream &operator<<(ostream &out, const Sample s) { cout << s.x << endl; return out; }
以上代码在gnuc++中编译运行毫无问题。可是在VC++6.0中编译的时候就会出现如下的编译错误:code
Compiling… Sample.cpp c:\temp\sample.cpp(8) : error C2248: ‘x’ : cannot access private member declared in class ‘Sample’ c:\temp\sample.h(19) : see declaration of ‘x’ c:\temp\sample.cpp(13) : error C2248: ‘x’ : cannot access private member declared in class ‘Sample’ c:\temp\sample.h(19) : see declaration of ‘x’ Error executing cl.exe.Sample.obj – 2 error(s), 0 warning(s)
在VC++ 6.0中解决这个问题有如下几种方法:ci
在头文件中实现做为朋友函数的操做符函数的重载,也就是说在实现文件”Sample.cpp”中将函数重载的实现去掉,而将头文件修改以下:原型
// 修改后的头文件 1 "Sample.h" #include<iostream> using namespace std; class Sample { public: Sample(); friend ostream &operator<<(ostream &out, const Sample s); friend ostream &operator<<(ostream &out, const Sample s) { cout << s.x << endl; return out; } friend istream &operator>>(istream &in, Sample & s); friend istream &operator>>(istream &in, Sample & s) { cout<<"Please enter a value"<<endl; in >> s.x ; return in; } private: int x; };
在头文件中类定义以前将类和朋友操做符函数的原型特别声明一下,也就是将头文件修改以下(实现文件”Sample.cpp”不用做任何修改):编译器
// 修改后的头文件 2 "Sample.h" #include<iostream> using namespace std; // 如下3行代码为新加入 class Sample; ostream &operator<<(ostream &out, const Sample s); istream &operator>>(istream &in, Sample & s); class Sample { public: Sample(); friend ostream &operator<<(ostream &out, const Sample s); friend istream &operator>>(istream &in, Sample & s); private: int x; };
第三种方法是对I/O名空间的使用实行明确声明,也就是说在头文件”Sample.h”中直接写:io
#include<iostream> using std::ostream; using std::istream ….
取代 “using namespace std;”
注意:在这个例子里咱们在实现文件 “Sample.cpp”中包含 “using namespace std;”这句话,不然在实现中就不能使用 “cout” , “cin”, “<< “, “>>” 和 endl 这些关键字和符号。修改后的完整代码以下:编译
// Sample.h #include<iostream> using std::istream; using std::ostream; class Sample { public: Sample(); friend ostream &operator<<(ostream &out, const Sample s); /*friend ostream &operator<<(ostream &out, const Sample s) { cout << s.x << endl; return out; }*/ friend istream &operator>>(istream &in, Sample & s); /*friend istream &operator>>(istream &in, Sample & s) { cout<<"Please enter a value"<<endl; in >> s.x ; return in; }*/ private: int x; }; // "Sample.cpp" #include "Sample.h" using namespace std; Sample::Sample() { x=5; } istream &operator>>(istream &in, Sample & s) { cout<<"Please enter a value"<<endl; in >> s.x ; return in; } ostream &operator<<(ostream &out, const Sample s) { cout << s.x << endl; return out; }