随笔 - 30, 文章 - 0, 评论 - 64, 引用 - 0
数据加载中……

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 阅读(2335) 评论(5)  编辑 收藏 引用 所属分类: C++

评论

# re: VC6.0中重载操作符函数无法访问类的私有成员  回复  更多评论   

能讲解一下其内在原因是什么吗?
2008-12-09 09:45 | abettor

# re: VC6.0中重载操作符函数无法访问类的私有成员  回复  更多评论   

猜测的成分太多了,friend function好像不是翻成朋友函数,叫友元吧
2008-12-09 09:51 | zuhd

# re: VC6.0中重载操作符函数无法访问类的私有成员  回复  更多评论   

visual c++ 2005 就支持了
2008-12-10 21:45 | 漂漂

# re: VC6.0中重载操作符函数无法访问类的私有成员  回复  更多评论   

hanxiaodkf
2009-07-14 16:50 | han

# re: VC6.0中重载操作符函数无法访问类的私有成员[未登录]  回复  更多评论   

Thanks
2012-06-25 09:43 | yong

只有注册用户登录后才能发表评论。
网站导航: 博客园   IT新闻   BlogJava   博问   Chat2DB   管理