为什么C++赋值运算符重载函数不能被继承?
来源:互联网 发布:ubuntu mate 安装pyqt 编辑:程序博客网 时间:2024/06/13 23:04
为什么C++赋值运算符重载函数不能被继承?
这个问题曾经困扰过我一阵子。请先看一下下面的源代码:
我又查找了C++ Primer和其他一些重量级的C++经典,可是这些书籍对此问题都避而不谈,抑或是语焉不详,我都没有找到答案。于是,我只好反身求诸己,从C++类对象的构造开始分析,结果找到了我认为是正确的答案:
1,每一个类对象实例在创建的时候,如果用户没有定义“赋值运算符重载函数”,那么,编译器会自动生成一个隐含和默认的“赋值运算符重载函数”。所以,B1的实际上的声明应该类似于下面这种情况:
2,C++标准规定:如果派生类中声明的成员与基类的成员同名,那么,基类的成员会被覆盖,哪怕基类的成员与派生类的成员的数据类型和参数个数都完全不同。显然,B1中的赋值运算符函数名operator =和基类A1中的operator =同名,所以,A1中的赋值运算符函数int perator=(int a);被B1中的隐含的赋值运算符函数B1& perator =(const B1& robj);所覆盖。 A1中的int perator=(int a);函数无法被B1对象访问。
3,程序中语句v = 2实际上相当于v.operator =(2);,但是A1中的int perator=(int a);已经被覆盖,无法访问。而B1中默认的B1& perator =(const B1& robj);函数又与参数2的整数类型不相符,无法调用。
4,为了确认B1中默认的B1& perator =(const B1& robj);函数的存在性,可以用以下代码验证:
5,所以,“赋值运算符重载函数”不是不能被派生类继承,而是被派生类的默认“赋值运算符重载函数”给覆盖了。
这就是C++赋值运算符重载函数不能被派生类继承的真实原因!
C++程序员的必读经典《Effective C++》这么说:
条款45: 弄清C++在幕后为你所写、所调用的函数
一个空类什么时候不是空类? ---- 当C++编译器通过它的时候。如果你没有声明下列函数,体贴的编译器会声明它自己的版本。这些函数是:一个拷贝构造函数,一个赋值运算符,一个析构函数,一对取址运算符。另外,如果你没有声明任何构造函数,它也将为你声明一个缺省构造函数。所有这些函数都是公有的。换句话说,如果你这么写:
和你这么写是一样的:
这个问题曾经困扰过我一阵子。请先看一下下面的源代码:
class A1{public: int perator=(int a) { return 8; } int operator+(int a) { return 9; }};class B1 : public A1{public: int operator-(int a) { return 7; }};int main(){ B1 v; cout << (v + 2) << endl; // OK, print 9 cout << (v - 2) << endl; // OK, print 7 cout << (v = 2) << endl; // Error, see below return 0;}
VC编译器的错误提示:
error C2679: binary '=' : no operator defined which takes a right-hand operand of type 'const int' (or there is no acceptable conversion)
意思是说编译器找不到int perator=(int a)这个成员函数可以调用。
真是怪了?明明int perator=(int a)这个函数是我从基类公有继承下来的函数,怎么编译器识别不了呢?遇到这种问题,第一反应就是查找MSDN以求得解释,微软告诉我:
“All overloaded operators except assignment (operator=) are inherited by derived classes.”
意思是说:除了赋值运算符重载函数以外,所有的运算符重载函数都可以被派生类继承。
我这个函数int perator=(int a)很不幸就是微软所说的“赋值运算符重载函数”,当然不能被继承!
可是到此为止,我心中的疑问依然没有消除。为什么“赋值运算符重载函数”不能被派生类继承呢?从C++语义上讲,不允许这个函数被派生类继承并没有充足的理由,一个类对象实例完全可以被任何一个其他类对象实例所赋值!比如一个颜色对象实例可以被一个整数赋值,甚至可以被一个小白兔实例所赋值。赋值运算符既然允许重载,就应该允许被继承,就像其他的运算符重载之后都可以被派生类继承一样。微软的解释并没有说明为什么“赋值运算符重载函数”不能被继承的幕后原因。
我又查找了C++ Primer和其他一些重量级的C++经典,可是这些书籍对此问题都避而不谈,抑或是语焉不详,我都没有找到答案。于是,我只好反身求诸己,从C++类对象的构造开始分析,结果找到了我认为是正确的答案:
1,每一个类对象实例在创建的时候,如果用户没有定义“赋值运算符重载函数”,那么,编译器会自动生成一个隐含和默认的“赋值运算符重载函数”。所以,B1的实际上的声明应该类似于下面这种情况:
class A1{public: int perator=(int a) { return 8; } int operator+(int a) { return 9; }};class B1 : public A1{public: B1& operator =(const B1& robj); // 注意这一行是编译器添加的 int operator-(int a) { return 7; }};
2,C++标准规定:如果派生类中声明的成员与基类的成员同名,那么,基类的成员会被覆盖,哪怕基类的成员与派生类的成员的数据类型和参数个数都完全不同。显然,B1中的赋值运算符函数名operator =和基类A1中的operator =同名,所以,A1中的赋值运算符函数int perator=(int a);被B1中的隐含的赋值运算符函数B1& perator =(const B1& robj);所覆盖。 A1中的int perator=(int a);函数无法被B1对象访问。
3,程序中语句v = 2实际上相当于v.operator =(2);,但是A1中的int perator=(int a);已经被覆盖,无法访问。而B1中默认的B1& perator =(const B1& robj);函数又与参数2的整数类型不相符,无法调用。
4,为了确认B1中默认的B1& perator =(const B1& robj);函数的存在性,可以用以下代码验证:
B1 b;B1 v;v = b; // OK, 相当于调用v.operator =(b);
5,所以,“赋值运算符重载函数”不是不能被派生类继承,而是被派生类的默认“赋值运算符重载函数”给覆盖了。
这就是C++赋值运算符重载函数不能被派生类继承的真实原因!
C++程序员的必读经典《Effective C++》这么说:
条款45: 弄清C++在幕后为你所写、所调用的函数
一个空类什么时候不是空类? ---- 当C++编译器通过它的时候。如果你没有声明下列函数,体贴的编译器会声明它自己的版本。这些函数是:一个拷贝构造函数,一个赋值运算符,一个析构函数,一对取址运算符。另外,如果你没有声明任何构造函数,它也将为你声明一个缺省构造函数。所有这些函数都是公有的。换句话说,如果你这么写:
class Empty{};
和你这么写是一样的:
class Empty {public: Empty(); // 缺省构造函数 Empty(const Empty& rhs); // 拷贝构造函数 ~Empty(); // 析构函数 ---- 是否 // 为虚函数看下文说明 Empty& perator=(const Empty& rhs); // 赋值运算符 Empty* operator&(); // 取址运算符 const Empty* operator&() const;};
0 0
- 为什么C++赋值运算符重载函数不能被继承?
- 为什么C++赋值运算符重载函数不能被继承?
- 为什么C++赋值运算符重载函数不能被继承?
- 为什么C++赋值运算符重载函数不能被继承?
- 为什么C++赋值运算符重载函数不能被继承?
- 为什么C++赋值运算符重载函数不能被继承?
- 为什么C++赋值运算符重载函数不能被继承?
- 为什么C++赋值运算符重载函数不能被继承? 【转】
- 赋值运算符重载函数被继承了吗?
- 赋值运算符重载函数[C/C++/C#]
- 赋值运算符重载函数
- 赋值运算符重载函数
- C++:赋值运算符重载
- [C++]拷贝构造函数和赋值运算符重载
- 流运算符为什么不能重载为成员函数,只能用友元函数重载
- 流运算符为什么不能重载为成员函数,只能用友元函数重载
- 重载赋值运算符(c/c++)
- 【c++】关于类继承运算符重载友元函数
- Android 不同应用之间互相通信以及读取资源
- 线段树
- Visual Studio 2010 SP1 中文升级补丁下载及说明
- 实用命令
- IOS之Quartz2D绘图5.绘制UITableViewCell渐变背景
- 为什么C++赋值运算符重载函数不能被继承?
- 最小生成树(Prim算法)
- 四个好看的CSS样式表格
- SQL Like 通配符
- 姐弟恋没结果的星女
- OpenCV c接口与c++接口
- linux kernel时间管理
- Android merge布局优化
- 获取手机信息