说明:文章中关于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 <iostream>
using namespace std;
#include <string>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()"<<endl;
}
Basic::Basic(string name)
{m_name = name ;cout <<"Basic::Basic(string)"<<"name:"<<m_name<<endl;
}
Basic::Basic(Basic &bc)
{this->m_name = bc.m_name;cout <<"Basic::Basic(Basic&)"<<"name:"<<bc.m_name<<endl;
}Basic::~Basic()
{cout<<"this is "<<m_name << "Basic::~Basic()"<<endl;;
}class Derived:public Basic
{
public:int m_dx;Derived();Derived(string name);//m_name~Derived();void show();
};
Derived::Derived()
{cout <<"Derived::Derived()"<<endl;
}
Derived::Derived(string name):Basic(name)
{cout <<"Derived::Derived(string)"<<"name:"<<m_name<<endl;
}
Derived::~Derived()
{cout <<"this is "<<m_name <<"Derived::~Derived()"<<endl;;
}
void Derived::show()
{cout<<"name: "<<m_name<<endl;
}
void test()
{Derived dc1("dc1");cout<<""<<endl;Derived dc2("dc2");//m_bxcout<<""<<endl;dc1 = dc2 ;//Basic::operator=() 调用了基类的operator= ,并正确地对Derived::m_name进行了赋值。 看起来是operator=被继承了?分析见下5补充。    cout<<"next is dc1.show():  ";dc1.show();cout<<""<<endl;
}
int main() {test();while(1);
}
/**
Basic::Basic(string)name:dc1
Derived::Derived(string)name:dc1Basic::Basic(string)name:dc2      //生成派生类对象时,先调用基类的构造函数
Derived::Derived(string)name:dc2  //在调用自身的构造函数Basic::operator=()  //调用了基类的operator= ,并正确地对Derived::m_name进行了赋值。             //测试时,假如把基类的operator=实现为空函数,那么Derived对象也不能对Derived::m_name进行重新赋值。除非再手动实现Derived的operator=。            //operator= 只有一个,Drived中如果手动实现了,将会覆盖基类的=。就是说,不会执行基类的operator=。
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 <iostream>
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;return 0;}
};class B1 : public A1
{
public:int operator-(int a){return 7;}#if 1using A1::operator= ;
#endif};void test_common()
{B1 v;cout << (v + 2) << endl; // OK, print 9cout << (v - 2) << endl; // OK, print 7
cout << (v = 2) << 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 <iostream>
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)"<<endl;this->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:"<<v.GetVal()<<endl;//11
B v2(22,33);cout<<"get value:"<<v2.GetVal()<<endl;//22cout<<"get valueB:"<<v2.GetValB()<<endl;//33
v2 = v  ; // operator=(A1 &a) cout<<"get value:"<<v2.GetVal()<<endl;// 110   执行了基类的operator=cout<<"get valueB:"<<v2.GetValB()<<endl;// 44  这里是系统默认生产的。// 打印operator=(A1 &a) 说明给派生类赋值时,执行了 基类operator= 。// 虽然执行了基类的operator=,但是基类operator=没有办法对派生类增加的成员变量赋值,剩下的操作就由系统默认给定(按对象的内存地址依次复制)。// [基类operator=为什么在这里会执行,是不是和构造函数的相同,必然会执行呢?答案是否定的,当B自定义了operator=之后,不会执行基类中的operator=。]
}
int main()
{        test_inheritance();while(1);return 0;
}

参考:

1.构造与析构函数与 operator=不能被继承
  http://www.cnblogs.com/findumars/p/3695340.html

2.为什么C++赋值运算符重载函数不能被继承?
  http://www.eetop.cn/blog/html/11/317611-14436.html

3.C++重载运算符的继承

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

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

c++, 派生类的构造函数和析构函数 , [ 以及operator=不能被继承 or Not的探讨]相关推荐

  1. php 派生类 构造,C++派生类的构造函数和析构函数

    派生类对象中包含基类对象,因此派生类对象在创建时,除了要调用自身的构造函数进行初始化外,还要调用基类的构造函数初始化其包含的基类对象.因此,程序中任何能够生成派生类对象的语句,都要说明其包含的基类对象 ...

  2. C++派生类的构造函数和析构函数

    C++派生类的构造函数和析构函数 派生类的构造函数和析构函数 #include <iostream> using namespace std; class student { public ...

  3. C++中基类与派生类的构造函数和析构函数

    1.Cpp中的基类与派生类的构造函数 基类的成员函数可以被继承,可以通过派生类的对象访问,但这仅仅指的是普通的成员函数,类的构造函数不能被继承.构造函数不能被继承是有道理的,因为即使继承了,它的名字和 ...

  4. 派生类的构造函数和析构函数

    一.简单派生类的析构函数和构造函数. 1.简单派生类构造函数的定义形式:派生类构造函数名 (总参数表列):基类构造函数名 (参数表列){ 派生类新增加数据成员初始化语句} 其中,总参数表列中的参数包括 ...

  5. c++派生类和基类的构造函数和析构函数

    基类和派生类的构造函数顺序,先调用基类的构造函数,在调用派生类的构造函数, 析构函数而言,先调用派生类的析构函数,再调用基类的析构函数 #include<iostream> using n ...

  6. 6.12C++:继承基类的构造函数、单继承的构造函数、多继承的构造函数、派生类复制构造函数、派生类的析构函数

    1 继承基类的构造函数 class A{public:A(){}; // A的构造函数 }; class B : public A{public:using A:A: } 2 单继承的构造函数 cla ...

  7. 派生类中构造函数与虚构函数的研究

    1.继承过程中的构造函数 A:继承与派生过程中,基类的构造函数不能被继承,派生类中需要声明自己的构造函数. B:声明构造函数时,只需要对本类中新增成员进行初始化.至于基类继承过来的成员,应该调用基类的 ...

  8. C++类的构造函数、析构函数与赋值函数

    C++类的构造函数.析构函数与赋值函数 构造函数.析构函数与赋值函数是每个类最基本的函数.它们太普通以致让人容易麻痹大意,其实这些貌似简单的函数就象没有顶盖的下水道那样危险. 每个类只有一个析构函数和 ...

  9. 基类和派生类的构造函数,隐式调用与显式调用

    1. 顺序        当创建一个派生类的对象时,系统首先自动创建一个基类对象,也就是说,在调用派生类构造函数创建派生类对象之前,系统首先调用基类的构造函数创建基类对象.当派生类对象生命期结束时,首 ...

最新文章

  1. boost::asio使用UDP协议通信源码实现
  2. Splay ---- 2018牛客多校第三场 区间翻转搞区间位移 或者 rope可持久化块状链表
  3. svn 服务器在生产环境中的搭建
  4. 字符集详解 ------------------------ UNICODE +UTF8
  5. 563. 二叉树的坡度
  6. C++ template函数模板
  7. Gitlab+Jenkins学习之路(九)之Jenkins的远程管理和集群
  8. HDFS-HA的配置-----自动Failover
  9. 如何在Mac上将iCloud照片库备份到Mac硬盘?
  10. Hyrax: Doubly-efficient zkSNARKs without trusted setup学习笔记
  11. 下载 沙耶之歌Android_沙耶之歌安卓版
  12. 在RecyclerView里使用图片轮播
  13. Unirech腾讯云代充-云服务器登陆及远程连接常见问题
  14. Js一句话实现打开QQ和客服聊天
  15. App数据分析到底要分析什么
  16. 可发教育类论文的期刊《家长》简介及投稿邮箱
  17. SpringBoot框架的优点
  18. 有什么性价比高的蓝牙耳机?2022三八节适合送礼的蓝牙耳机品牌推荐
  19. Android12指纹框架完全解析(一)
  20. 欧姆龙 PLC CP1E 与电子称重仪表“柯力XK3101”Modbus RTU通信,稍微更改下Modbus通信地址可以跟其他Modbus设备进行通信

热门文章

  1. 是北京晚报!不,是中国最大的讽刺!!!
  2. 以太坊数据结构MPT
  3. github创建静态页面_如何在10分钟内使用GitHub Pages创建免费的静态站点
  4. python构建json_如何使用Python构建JSON API
  5. 安卓java代码标签_Android实现动态添加标签及其点击事件
  6. (C++)1015 德才论
  7. 参加web前端开发培训具体要学什么内容
  8. 69亿美元英伟达史上最大收购!这家基金又赢了
  9. JPA 复杂查询 - Querydsl
  10. 设置grep高亮显示匹配项