关于C++中操作符重载的疑问 :四个运算符=, ->, [], ()不可以重载为全局函数(友员函数)
C++规定有四个运算符 =, ->, [], ()不可以是全局域中的重载(即不能重载为友员函数),这是为什么呢?
现在先说说赋值运算符“=”的重载
C++规定赋值运算符“=”只能重载为类的非静态成员函数,而不可以重载为类的友元函数。
不能重载为类的静态成员应该比较容易理解,因为静态成员函数是属于整个类的,不是属于某个对象的,它只能去操作类静态数据成员。而赋值运算符“=”是基于对象操作的。
那么为什么赋值运算符不可以重载为类的友元函数?像同样都是双目运算符的+为什么它就可以呢?
在讨论这问题之前,先看一测试的程序:
#include <iostream>
using namespace std;
class A
{
private:
int x;
public:
A(){x=99;}
A(int xx)
{
cout<<"Call A(int xx)"<<endl;
x = xx;
}
};
int main()
{
A a;
a = 7;
}
程序执行结果为:
Call A(int xx)
说明执行a = 7这程序语句时,程序去调用类A中的带参构造函数。
在类A中加入一赋值运算重载成员函数,如下:
#include <iostream>
using namespace std;
class A
{
private:
int x;
public:
A(){x=99;}
A(int xx)
{
cout<<"Call A(int xx)"<<endl;
x = xx;
}
A operator=(int xx) //重载赋值运算符运算
{
cout<<"Call A operator=(int xx)"<<endl;
x = xx;
return *this;
}
};
int main()
{
A a;
a = 7;
}
程序运行结果:
Call A operator=(int xx)
说明在类A中已经有相应赋值运算符重载函数的时候,执行赋值语句a = 7;程序会去调用类A中相应的赋值运算符重载函数,而不会像上面原来那样去调用有参构造函数。
在此,我们可以对C++规则做出以下的判断:
当类中没有定义赋值运算符重载成员函数时(注意,在未定义形参数据类型为该类类型的赋值运算符重载函数时,编译器会自动生成加入),当程序执行到某一赋值语 句时,程序就会调用与赋值语句中右值类型匹配的构造函数,而把这右值当作此构造函数的实参。像最初的赋值语句a = 7,执行时,实际做的操作是a(7)。而当类中有定义赋值运算符重载成员函数,执行赋值语句时,程序就只会去调用相应的赋值运算符重载函数。
当明白上面的规则后,现在就可以回过来,讨论为什么赋值运算符不可以重载为类的友元函数了。
我们知道友元函数不是类的成员函数,它只是类的“朋友“,具有访问把它声明为“朋友”的类的数据成员的权限而已。
那么当把赋值运算符重载为类的友员函数,在程序中执行类对象的赋值语句时,程序就会出现两种矛盾的选择。
1、因为它认为类中并没有重载赋值运算符的成员函数,所以它根据C++的规则,会去调用相应的构造函数。
2、但是在全局里,我们已经重载了参数类型为此类类型的赋值运算符函数,而这赋值语句刚好和这函数匹配上了,根据C++的规则,也会去调用这函数。
程序是不允许有矛盾不确定选择的,所以当赋值运算符重载为类的友元函数时,编译器就会提示错误。
对于剩下的3个运算符 ->, [], () 为什么不能重载为友元函数,也是跟上面一样的道理。即编译器发现当类中没有定义这3个运算符的重载成员函数时,就会自己加入默认的运算符重载成员函数。
例当类A中没有定义运算符->的重载成员函数,但是我们仍然可以对类A对象指针用->的形式调用指针指向的对象里的成员。像类A里有成员函数f(),当
A a;
A* p = &a;
p->f(); //虽然类A中没有自己定义运算符->重载成员函数,但这里仍可这样使用
然而,当我们把->运算符重载为类A的友元函数时,程序就会出现跟把赋值运算符重载友元一样的情况,即产生矛盾性。
总结来说,这几个运算符不能重载为友元函数的原因就是,C++一个类本身对这几个运算符已经有相应的解释了。

低调大师中文资讯倾力打造互联网数据资讯、行业资源、电子商务、移动互联网、网络营销平台。
持续更新报道IT业界、互联网、市场资讯、驱动更新,是最及时权威的产业资讯及硬件资讯报道平台。
转载内容版权归作者及来源网站所有,本站原创内容转载请注明来源。
- 上一篇
简述C和C++的学习历程
总是被问到,如何学习C和C++才不茫然,才不是乱学,想了一下,这里给出一个总的回复。一家之言,欢迎拍砖哈。1、可以考虑先学习C.大多数时候,我们学习语言的目的,不是为了成为一个语言专家,而是希望成为一个解决问题的专家。做一个有用的程序员,做一个赚钱的程序员。我们的价值,将体现在客户价值上,而不是语言写得好不好看。C++是C的一个面向对象的解释,C++为C扩充了大规模工程应用,复杂的系统结构的组织和掌控方法,但是,我认为,C++骨子里还是C的。毕竟,解决具体问题,每个函数内部,都是用C的方式写程序,还是面向过程的。因此,想要学习好C++,我的建议,先学习C,先学解决问题的能力,再讨论解决大问题的能力。就是先学习怎么走路,再学习怎么跑步。2、学习C的过程中,一定要理解结构化编程思维。为什么呢,我前面有文章说过,软件语言的发展过程,就是一个数据私有化的过程,大型工程应用,强调高内聚,低耦合,模块化设计,保持代码最大的灵活性和安全性。这是现代工程化开发的核心和灵魂。因此,利用C这门语言入门,借此理解结构化开发思维,可以说是个很方便的路子。因为C的函数,本来就是为重用做准备的。同时,全局变量和c...
- 下一篇
C++的函数对象优于函数指针地方
转载自:http://blog.csdn.net/huang_xw/article/details/7934156 在C++编程语言中,有很多功能都与C语言相通,比如指针的应用等等。在这里我们介绍的则是一种类似于函数指针的C++函数对象的相关介绍。C++函数对象不是函数指针。但是,在程序代码中,它的调用方式与函数指针一样,后面加个括号就可以了。这是入门级的随笔,说的是函数对象的定义,使用,以及与函数指针,成员函数指针的关系。 C++函数对象实质上是一个实现了operator()--括号操作符--的类。 下面是函数对象与函数指针的例子: namespace { class AddCls { public: int operator()(int a, int b) { return a + b; } }; int AddFunc(int a, int b) { return a + b; } } void test_addObj() { // 定义函数对象 AddCls addObj; PRINT_DEBUG(addObj(3, 4); } void test_addFunP...
相关文章
文章评论
共有0条评论来说两句吧...
文章二维码
点击排行
推荐阅读
最新文章
- Linux系统CentOS6、CentOS7手动修改IP地址
- CentOS关闭SELinux安全模块
- CentOS8安装Docker,最新的服务器搭配容器使用
- SpringBoot2编写第一个Controller,响应你的http请求并返回结果
- Hadoop3单机部署,实现最简伪集群
- SpringBoot2初体验,简单认识spring boot2并且搭建基础工程
- Eclipse初始化配置,告别卡顿、闪退、编译时间过长
- Springboot2将连接池hikari替换为druid,体验最强大的数据库连接池
- Windows10,CentOS7,CentOS8安装Nodejs环境
- 设置Eclipse缩进为4个空格,增强代码规范