在 C++ 中,操作符(運(yùn)算符)可以被重載以改寫其實(shí)際操作。
同時我們可以定義一個函數(shù)為類的朋友函數(shù)(friend function)以便使得這個函數(shù)能夠訪問類的私有成員,
這個定義通常在頭文件中完成。
在Visual C++中定義一般的函數(shù)為朋友函數(shù)通常是沒有問題的。
然而對某些重載操作符的函數(shù),
即使我們將它們定義為類的朋友函數(shù),VC的編譯器仍然會顯示出錯信息,
認(rèn)為這些朋友函數(shù)無權(quán)訪問類的私有成員。
我認(rèn)為這應(yīng)該是VC6.0的bug。
以下代碼就是個例子:
// 頭文件 “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;
};
|
// 實(shí)現(xiàn)文件 “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++中編譯運(yùn)行毫無問題。但是在VC++6.0中編譯的時候就會出現(xiàn)以下的編譯錯誤:
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中解決這個問題有以下幾種方法:
- 在頭文件中實(shí)現(xiàn)作為朋友函數(shù)的操作符函數(shù)的重載,也就是說在實(shí)現(xiàn)文件”Sample.cpp”中將函數(shù)重載的實(shí)現(xiàn)去掉,而將頭文件修改如下:
// 修改后的頭文件 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;
};
|
- 在頭文件中類定義之前將類和朋友操作符函數(shù)的原型特別聲明一下,也就是將頭文件修改如下(實(shí)現(xiàn)文件”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名空間的使用實(shí)行明確聲明,也就是說在頭文件”Sample.h”中直接寫:
#include<iostream>
using std::ostream;
using std::istream
….
取代 “using namespace std;”
注意:在這個例子里我們在實(shí)現(xiàn)文件 “Sample.cpp”中包含 “using namespace std;”這句話,否則在實(shí)現(xiàn)中就不能使用 “cout” , “cin”, “<< “, “>>” 和 endl 這些關(guān)鍵字和符號。修改后的完整代碼如下:
// 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;
}
|