博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
c++, 派生类的构造函数和析构函数 , [ 以及operator=不能被继承 or Not的探讨]
阅读量:4635 次
发布时间:2019-06-09

本文共 4197 字,大约阅读时间需要 13 分钟。

 说明:文章中关于operator=实现的示例,从语法上是对的,但逻辑和习惯上都是错误的。

参见另一篇专门探究operator=的文章:《c++,operator=》http://www.cnblogs.com/mylinux/p/4113266.html

 

1.构造函数与析构函数不会被继承;[1]

  不是所有的函数都能自动地从基类继承到派生类中的。构造函数和析构函数是用来处理对象的创建和析构的,它们只知道对在它们的特殊层次的对象做什么。所以,在整个层次中的所有的构造函数和析构函数都必须被调用,也就是说,构造函数和析构函数不能被继承。

  另外,operator= 也不能被继承,因为它完成类似于构造函数的活动。//All overloaded operators except assignment (operator=) are inherited by derived classes.

2.派生类的构函数被调用时,会先调用基类的其中一个构造函数,因为在派生类的构造函数中用了初始化表的方式调用了基类构造函数,默认不写时是调用了基类中可以不传参数的构造函数。

3.在派生类对象释放时,先执行派生类析构函,再执行其基类析构函数。

#include 
using namespace std;#include
class Basic{public: string m_name; Basic(); Basic(string name); Basic(Basic& bc); ~Basic(); Basic& operator=(const Basic& bc) { cout << "Basic::operator=()\n"; this->m_name = bc.m_name; return *this; }};Basic::Basic(){ cout <<"Basic::Basic()"<
m_name = bc.m_name; cout <<"Basic::Basic(Basic&)"<<"name:"<
<
next is dc1.show(): name: dc2 this is dc2Derived::~Derived() //析构和构造的调用顺序刚好相反。先调用自身的析构函数,再调用基类的析构函数。 this is dc2Basic::~Basic() this is dc2Derived::~Derived()//在一个函数体中,先实现的对象后释放。 this is dc2Basic::~Basic() **/

 

4.派生类构造函数首行的写法:

class Basic{public:    int m_number;    string m_name ;    char m_sex;//'m' 'w'    Basic(int n ,string name , char s);};Basic::Basic(int n,string name ,char s)    :m_number(n)    ,m_name(name)    ,m_sex(s){//     this->m_name = name;//     this->m_number = n;//     this->m_sex = s;}class Derived:public Basic{public:    int m_age;    string m_addr;    Derived(int n,string name,char s,int a, string addr);};Derived::Derived(int n,string name,char s,int a, string addr)    :Basic(n,name,s)    ,m_age(a)    ,m_addr(addr){}

 

5.  operator=不能被继承 or Not的探讨

关于operator=的说法比较有争议,以下面的实验结果为准。

(1) operator= 不能被继承[2](个人认为,拷贝形式的除外,否则不能解释上面代码的打印结果以及下面代码的实验结果)。

    //MSDN: All overloaded operators except assignment (operator=) are inherited by derived classes.

    [如果非要说不能够继承,那也会调用基类中的拷贝式operator=。]

(2)通过使用“using 某类::operator某运算符”语句,就可以继承基类中的运算符了。[3]

 

//下面的实验说明 // 1. 一般的operator=不会被继承。// 2.通过使用“using 某类::operator某运算符”语句,就可以“继承”基类中的运算符了。而如果没有加上该语句,编译会出错。// 3.msdn和C++的国际标准《ISO/IEC 14882》都说了operator=不能被继承,但是通过在vs2010中的实验,在派生类没有自定义operator=的情况下,派生了会执行基类中的拷贝式operator=。 // 【对于派生类增加的变量赋值,系统默认给定,具体例子见下面的补充说明】#include 
using namespace std ; class A1{public: int operator=(int a) { return 8; } int operator+(int a) { return 9; } int operator=(A1 &a) { cout<<"operator=(A1 &a)"<
<< endl; // 如果class B1加了 using A1::operator= ; ,强行“继承”了A1的operator=,则结果为8. // 否则: error C2679: 二进制“=”: 没有找到接受“int”类型的右操作数的运算符(或没有可接受的转换)。}void test_copy(){ B1 v2; B1 v3; v2 = v3 ;//打印效果: operator=(A1 &a) //并且拷贝性质的operator=,从效果上看,能够被继承。 //拷贝性质的operator=,如果基类未对其显式地定义,始终还是能被编译器隐式的定义。}int main(){ test_common(); test_copy(); while(1); return 0;}

关于operator是否继承的问题,下面补充一下:

//下面的实验说明 // 1. 一般的operator=不会被继承。// 2.通过使用“using 某类::operator某运算符”语句,就可以“继承”基类中的运算符了。而如果没有加上该语句,编译会出错。// 3.msdn和C++的国际标准《ISO/IEC 14882》都说了operator=不能被继承,// 但是通过在vs2010中的实验说明:虽然说不能够继承,但是也会调用执行基类中的拷贝式operator=。// 4.那么执行了基类的operator=,但是基类operator=没有办法对派生类增加的成员变量赋值,剩下的操作就由系统默认给定(按对象的内存地址依次复制)。//   #include 
using namespace std ;/class A1{public: int operator=(int a) { return a; } A1& operator=(const A1 &a); A1(int val); int GetVal();private: int m_x;};A1::A1(int val):m_x(val){ }int A1::GetVal(){ return this->m_x;}A1& A1::operator=(const A1 &a) { cout<<"operator=(A1 &a)"<
m_x = a.m_x *10 ;//注意*10是为了看效果 return *this;}/class B:public A1{ private: int m_b;public: B(int vala,int valb); int GetValB() { return m_b; }};B::B(int vala,int valb):A1(vala),m_b(valb){}/////void test_inheritance(){ B v(11,44); cout<<"get value:"<
<

 

参考:

1.构造与析构函数与 operator=不能被继承

  http://www.cnblogs.com/findumars/p/3695340.html

2.为什么C++赋值运算符重载函数不能被继承?

  http://www.eetop.cn/blog/html/11/317611-14436.html 

3.

  http://blog.csdn.net/raodotcong/article/details/5501181

转载于:https://www.cnblogs.com/mylinux/p/4094808.html

你可能感兴趣的文章
数据结构之shell排序
查看>>
CodeForces 375D Tree and Queries
查看>>
牛客~~打篮球~~~模拟水题
查看>>
LeetCode-198. 打家劫舍
查看>>
5 -- Hibernate的基本用法 --2 1 Hibernate 下载和安装
查看>>
Socket
查看>>
【C#公共帮助类】10年代码,最全的系统帮助类
查看>>
JQuery UI
查看>>
张弛有度
查看>>
【ZJOI2008】树的统计(树链剖分)
查看>>
【NOIP校内模拟】T2 华莱士(环套树)
查看>>
lists,tuples and sets of Python
查看>>
Superset配置hive数据源
查看>>
查询Master下的系统表和系统视图获取数据库的信息和简单的渗透测试
查看>>
GET和POST的区别
查看>>
Sublime Text 3 及Package Control 安装(附上一个3103可用的Key)
查看>>
jvm 性能调优
查看>>
算法(第四版)C# 习题题解——1.3
查看>>
LTE QCI分类 QoS
查看>>
【Flask】flask+uwsgi+nginx环境部署
查看>>