VC6.0中重載操作符函數無法訪問類的私有成員
在 C++ 中,操作符(運算符)可以被重載以改寫其實際操作。
同時我們可以定義一個函數為類的朋友函數(friend function)以便使得這個函數能夠訪問類的私有成員,
這個定義通常在頭文件中完成。
在Visual C++中定義一般的函數為朋友函數通常是沒有問題的。
然而對某些重載操作符的函數,
即使我們將它們定義為類的朋友函數,VC的編譯器仍然會顯示出錯信息,
認為這些朋友函數無權訪問類的私有成員。
我認為這應該是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; }; |
// 實現文件 “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中編譯的時候就會出現以下的編譯錯誤:
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中解決這個問題有以下幾種方法:
- 在頭文件中實現作為朋友函數的操作符函數的重載,也就是說在實現文件”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”中直接寫:
#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; }
posted on 2008-12-08 23:50 henry08 閱讀(2359) 評論(5) 編輯 收藏 引用 所屬分類: C++