VC6.0中重载操作符函数无法访问类的私有成员
整理日: 2015年03月18日
在 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;
}
VC6.0中重载操作符函数无法访问类的私有成员的更多相关文章
- C#箴言之用属性来访问类的私有成员
在程序中,难免要访问某个对象的私有成员.那么以前实现这类功能的方法有两种,第一种方法最简单,就是把成员访问符从“private”改为“public”即可:而另一个就是提供公有的成员访问函数来进行访问. ...
- Delphi 跨单元进入(访问)类的私有成员,protected ,private部分
http://blog.sina.com.cn/s/blog_5f8861b60102v1nl.html Delphi 跨单元进入(访问)类的私有成员,protected ,private部分 (20 ...
- 使用C#反射机制访问类的私有成员【转】
首先我必须承认访问一个类的私有成员不是什么好做法.大家也都知道私有成员在外部是不能被访问的.而一个类中会存在很多私有成员:如私有字段.私有属性.私有方法.对于私有成员访问,可以套用下面这种非常好的方式 ...
- VC6.0中友元函数无法访问类私有成员的解决办法
举个例子: 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 #inclu ...
- [置顶] c++,vc6.0,中友元函数,无法访问私有字段(private)的问题(problem),cannot access private member declared in class 'Date'
c++,vc6.0,中友元函数,无法访问私有字段(private)的问题(problem),cannot access private member declared in class 'Date' ...
- 《从零开始学Swift》学习笔记(Day 7)——Swift 2.0中的print函数几种重载形式
原创文章,欢迎转载.转载请注明:关东升的博客 Swift 2.0中的print函数有4种重载形式: l print(_:).输出变量或常量到控制台,并且换行. l print(_:_:).输出 ...
- VC6.0中MFC界面换肤简例
利用VC中的MFC进行界面设计时,发现界面上的各控件无法简易地进行调整,比如字体大小.颜色.格式等. 为了改变外观,小小地美化一下,今天决定动手一试. 网上提供的库和方法不计其数,我选择了SkinMa ...
- [转贴]从零开始学C++之STL(二):实现一个简单容器模板类Vec(模仿VC6.0 中 vector 的实现、vector 的容量capacity 增长问题)
首先,vector 在VC 2008 中的实现比较复杂,虽然vector 的声明跟VC6.0 是一致的,如下: C++ Code 1 2 template < class _Ty, cl ...
- 在VC6.0中能不能使用Duilib界面库呢?
Duilib库的源代码是在vs2010下编译的,一般适用于vs2008及以上的版本开发使用,那么duilib能不能在vc6.0的工程中使用呢?如何在vc6.0中使用duilib库呢? 今天,由于工作要 ...
随机推荐
- ARCproject中加入非ARC文件,或者非ARC环境中加入ARC文件
ARC与非ARC在一个项目中同一时候使用, 选择项目中的Targets,选中你所要操作的Target,选Build Phases,在当中Complie Sources中选择须要ARC的文件双击,并在输 ...
- 修改Tomcat 6 默认的ROOT
1.找到conf/server.xml. 2.找到Host节点. 3.在该节点中添加子节点<Context path="" docBase="项目名称" ...
- [Node.js] Exporting Modules in Node
In this lesson, you will learn the difference between the exports statement and module.exports. Two ...
- [TypeScript] Installing TypeScript and Running the TypeScript Compiler (tsc)
This lesson shows you how to install TypeScript and run the TypeScript compiler against a .ts file f ...
- 构建tcpdump/wireshark pcap文件
pcap文件格式是bpf保存原始数据包的格式,很多软件都在使用,比如tcpdump.wireshark等等,了解pcap格式可以加深对原始数据包的了解,自己也可以手工构造任意的数据包进行测试. p ...
- android线程与线程池-----AsyncTask(一)《android开发艺术与探索》
线程在android是个重要的概念,从用途上讲,线程分为主线程和子线程,主线程负责页面相关,子线程负责耗时操作. 在android中除了Thread本身还有 AsyncTask IntentServ ...
- CentOS 6.7 安装配置BT下载工具Transmission
1.配置额外yum源 i386 cd /etc/yum.repos.d/ wget http://geekery.altervista.org/geekery-el6-i686.repo x86_64 ...
- Linux命令后台执行技巧小结
1.最简单的方法: command & 例如: top & 此时显示job编号和后台进程号 [] 2.正在运行的程序放入后台 Ctrl - Z 3.查看有哪些后台进程及状态 jobs ...
- springMVC+freemarker中Could not resolve view with name... 问题解决
用到springMVC+freemarker,自己在做demo过程中报: 严重: Servlet.service() for servlet springmvc threw exception jav ...
- mysql连接错误:Cannot get hostname for your address
问题 环境:win7 + 64Bit + 本地mysql5.6 问题:navicat连接本地mysql数据库,提示“Cannot get hostname for your address”,但是连接 ...