说明:文章中关于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_bx
cout<<""<<endl; dc1 = dc2 ;//Basic::operator=() 调用了基类的operator= ,并正确地对Derived::m_name进行了赋值。 看起来是operator=被继承了?分析见下5补充。
cout<<"next is dc1.show(): ";
dc1.show();
cout<<""<<endl;
}
int main() {
test();
while();
}
/**
Basic::Basic(string)name:dc1
Derived::Derived(string)name:dc1 Basic::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 ;
} int operator+(int a)
{
return ;
} int operator=(A1 &a)
{
cout<<"operator=(A1 &a)"<<endl;
return ;
}
}; class B1 : public A1
{
public:
int operator-(int a)
{
return ;
} #if 1
using A1::operator= ;
#endif }; void test_common()
{
B1 v;
cout << (v + ) << endl; // OK, print 9
cout << (v - ) << endl; // OK, print 7 cout << (v = ) << 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();
return ;
}

关于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是为了看效果
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(,);
cout<<"get value:"<<v.GetVal()<<endl;// B v2(,);
cout<<"get value:"<<v2.GetVal()<<endl;//
cout<<"get valueB:"<<v2.GetValB()<<endl;// 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();
return ;
}

参考:

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

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

  1. 不可或缺 Windows Native (21) - C++: 继承, 组合, 派生类的构造函数和析构函数, 基类与派生类的转换, 子对象的实例化, 基类成员的隐藏(派生类成员覆盖基类成员)

    [源码下载] 不可或缺 Windows Native (21) - C++: 继承, 组合, 派生类的构造函数和析构函数, 基类与派生类的转换, 子对象的实例化, 基类成员的隐藏(派生类成员覆盖基类成 ...

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

    4.2 派生类的构造函数和析构函数4.2.1 派生类构造函数和析构函数的执行顺序 通常情况下,当创建派生类对象时,首先执行基类的构造函数,随后再执行派生类的构造函数:当撤销派生类对象时,则先执行派生类 ...

  3. C++学习之路—继承与派生(二):派生类的构造函数与析构函数

    (根据<C++程序设计>(谭浩强)整理,整理者:华科小涛,@http://www.cnblogs.com/hust-ghtao转载请注明) 由于基类的构造函数和析构函数是不能被继承的,所以 ...

  4. C++:派生类的构造函数和析构函数的调用顺序

    一.派生类 在C++编程中,我们在编写一个基类的派生类时,大致可以分为四步: • 吸收基类的成员:不论是数据成员还是函数成员,派生类吸收除基类的构造函数和析构函数之外的全部成员. • 改造基类函数:在 ...

  5. C++学习笔记(6)----基类和派生类的构造函数和析构函数的执行顺序

    基类和派生类:构造函数和析构函数的执行顺序 在Visual Studio中,新建控制台工程,构造类如下: #include<iostream> using namespace std; c ...

  6. cc28c_demo.cpp,派生类的构造函数和析构函数-代码示范3

    cc28c_demo.cpp,派生类的构造函数和析构函数-代码示范3 //派生类的构造函数和析构函数//派生类的构造函数(执行步骤)//--执行基类的构造函数//--执行成员对象的构造函数//--执行 ...

  7. c++学习笔记4,派生类的构造函数与析构函数的调用顺序(一)

    測试源代码: //測试派生类的构造函数的调用顺序何时调用 //Fedora20 gcc version=4.8.2 #include <iostream> using namespace ...

  8. c++派生类中构造函数和析构函数执行顺序、判断对象类型、抽象类、虚函数

    一. 代码: 1 #include<stdio.h> 2 #include<string.h> 3 #include<algorithm> 4 #include&l ...

  9. c++ 单继承派生类的构造函数

    1.派生类的构造函数: #include <iostream> #include<string> using namespace std; class Student//声明基 ...

随机推荐

  1. Problem G: Keywords Search

    Problem G: Keywords SearchTime Limit: 1 Sec Memory Limit: 128 MBSubmit: 10 Solved: 6[Submit][Status] ...

  2. Struts学习之值栈的理解

    转自:http://blog.csdn.net/hanxuemin12345/article/details/38559979 页面一个请求发送过来,依次经过一系列拦截器(处理公共部分,如:往数据中心 ...

  3. .net 更改时间格式

    /// <summary> /// 更改时间格式[HH:mm:ss]到[HHmmss] /// </summary> /// <param name="inpu ...

  4. python的map()函数

    map()是 Python 内置的高阶函数,它接收一个函数 f 和一个 list,并通过把函数 f 依次作用在 list 的每个元素上,得到一个新的 list 并返回. 例如,对于list [1, 2 ...

  5. python 从数据库表生成model

    python 从数据库表生成model 找了很久才找到这个,我是新手... 现在已有建好的数据库,需要基于原有数据做数据分析的web应用,我选择python+Tornado ,由于不想写SQL语句,就 ...

  6. object-c 协议(Protocols)和代理(Delegation)的学习

    代理是Object-C中的一个重要机制,他可以将面向对象编程的封装特性进一步加强,不是自己负责的事情坚决不做,而是转而让对应的事情负责人(代理)去做.相反如果是自己需要负责的事情(作为别人的代理),会 ...

  7. LintCode-两数之和

    题目描述: 给一个整数数组,找到两个数使得他们的和等于一个给定的数target. 你需要实现的函数twoSum需要返回这两个数的下标, 并且第一个下标小于第二个下标.注意这里下标的范围是1到n,不是以 ...

  8. Delphi调试DLL 不能调试 不能进入调试 注意!!!

    如何调试DLL,在这里就不再赘述了,但是,今天就碰到了一个特别奇怪的问题,参数设置正确,就是不能调试?? 通过上网查资料,发现了问题,注意: 1, 将Project主菜单的Project Option ...

  9. HDU 1870 愚人节的礼物

    题解:简单的数括号问题…… #include <cstdio> char s[1005]; int main(){ while(scanf("%s",s)!=EOF){ ...

  10. PLSQL 导入表到Oracle------》从一个表空间导入到其它表空间

        在用PLSQL导入.dmp文件到Oracle时出现的问题如下: Import started on 2015/11/18 10:42:44E:\oracle\product\10.2.0\db ...