VC6.0中重載操做符函數沒法訪問類的私有成員

整理日: 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;
}
相關文章
相關標籤/搜索