C++ 派生类构造函数和析构函数
几个问题
一个类的各数据成员的构造顺序?
按他们在类定义中出现的先后顺序:先定义者先构造。
类的对象成员的构造函数与类自身的构造函数的执行顺序?
先执行对象成员的构造函数,再执行类自身的构造函数。
构造顺序与析构顺序的关系?
二者顺序相反:先构造者,后析构。
构造函数和析构函数用来创建和释放该类的对象,当这个类是派生类时,其对象的创建和释放应与其基类对象及成员对象相联系。
在声明派生类时,一般还应当自己定义派生类的构造函数和析构函数,因为构造函数和析构函数是不能从基类继承的 
派生类对象的创建和初始化与基类对象的创建和初始化有关。即构造派生类对象时,要对其基类数据成员、所含对象成员的数据成员以及其他的新增数据成员一起进行初始化。这种初始化工作是由派生类的构造函数来完成的。
派生类成员包括两部分:
(1)从基类继承的成员:由基类构造函数完成
(2)自身定义的成员: 由派生类构造函数完成

在派生类中,构造基类数据成员的可能方式:
方式一,在派生类中直接对基类型数据成员初始化:
class BC
{
public:
BC( )
{
x = y = -;
}
private:
int x, y;
};
class DC : public BC
{
public:
DC( )
{
x = y = -;//错误,不能构造基类的私有成员 error C2248: “B::x”: 无法访问 private 成员(在“B”类中声明)
}
private:
string S;
};
方式二,显示调用基类构造函数
class BC
{
public:
BC( )
{
x = y = -;
}
private:
int x, y;
};
class DC : public BC
{
public:
DC( )
{
BC( );//这是构造后才调用,语义错误
}
private:
string S;
};
这样的程序可以编译通过,但语意错误,这是派生类先构造后,在调用基类的构成函数。
正确构成基类数据成员的方式为:
class BC
{
public:
BC( )
{
x = y = -;
}
private:
int x, y;
};
class DC : public BC
{
public:
DC( ) : BC( ), S("派生类"), { }//初始化列表
private:
string S;
};
在创建派生类的对象时,需要调用基类的构造函数:初始化派生类对象从基类继承的成员。在执行一个派生类的构造函数之前,总是先执行基类的构造函数。
调用基类构造函数的两种方式:
(1)显式方式:在派生类的构造函数中,通过参数化表为基类的构造函数提供参数
derived::derived(arg_derived-list):base(arg_base-list)
(2)隐式方式:在派生类/基类的构造函数都缺省时,派生类的构造函数则自动调用基类的默认构造函数。
在一个多层次的继承层次结构中,一个派生类对象的创建时,其构造函数的调用有点类似于多米诺骨牌效应 (domino effect)

列出了不同情况下的派生类构造函数要求:

上面的例子其实也很好理解,我们知道:在执行一个派生类的构造函数之前,总是先执行基类的构造函数。
1.如果基类中无构造函数,那么对于派生类来说,不管派生类是何种构造函数,编译器都会先调用的执行基类的缺省构造函数,然后再执行派生类的构造函数。
2.如果基类是一个无缺省参数的构造函数,那么对于派生类一旦没有构造函数,那么就不会自动的先构造基类的构造函数,这是不允许的。
3.如果基类中有缺省参数的构造函数B(),那么派生类中没有构造函数也是允许的,编译器会自动调用。
通常, 一个基类有一个缺省构造函数。
以下做法是有其实际意义的:当一个派生类对象被创建时会引起某个基类的构造函数的执行。
(这条建议在派生类新增成员依赖于基类成员时体现非常明显)
class Team
{
public:
Team(int len =)
{
names = new string[maxno = len ];
//基类构造函数完成其成员初始化,供派生类构造使用。
}
protected:
string* names;
int maxno;
}; class BaseballTeam : public Team
{
public:
BaseballTeam(const string s[], int si)
: Team(si)//为支持派生类构造本意,必须明确调用基类构造函数。 {
for(int i=; i<si; i++)
names[i] = s[i];
//派生类构造函数执行前,基类构造必须完成。 }
};
执行构造函数的顺序:
1. 基类的构造函数
2. 子对象的构造函数
3. 其他数据成员初始化
继承下的析构函数 Destructors Under Inheritance

class BC
{
public:
BC( )
{
sBC = new char[];
cout << "BC allocates 3 bytes.\n";
}
~BC( )
{
delete [ ] sBC;
cout << "BC free 3 bytes.\n";
}
private:
char* sBC;
};
class DC : public BC
{
public:
DC( )
{
sDC = new char[];
cout << "DC allocates 5 bytes.\n";
}
~DC( )
{
delete [ ] sDC;
cout << "DC free 5 bytes.\n";
}
private:
char* sDC;
};
int main( )
{
DC d;
cout << “-------” << endl;
return ;
}

C++ 派生类构造函数和析构函数的更多相关文章
- C# 基类派生类构造函数执行顺序分析
using System; namespace ConsoleApp1 { class Program{ static void Main(string[] args){ B b = new B(); ...
- C++中虚继承派生类构造函数的正确写法
最近工作中某个软件功能出现了退化,追查下来发现是一个类的成员变量没有被正确的初始化.这个问题与C++存在虚继承的情况下派生类构造函数的写法有关.在此说明一下错误发生的原因,希望对更多的人有帮助. 我们 ...
- C++语言笔记系列之十三——派生类构造函数的调用
1.派生类构造函数的调用 (1)一个基类的全部数据成员均被派生类继承.创建一个派生类对象时.系统在为派生类对象分配单元时一定要为其基类数据成员分配子空间. (2)一个派生类对象在创建时不仅要调用派生类 ...
- C++的派生类构造函数是否要带上基类构造函数
//public:Student(int s_age):People(s_age) //C++的派生类构造函数后面是否带上基类构造函数,取决于基类构造函数是否需要传入参数,如果要参数,就一定带上:不需 ...
- C++类构造函数、析构函数运行机理
http://blog.sina.com.cn/s/blog_6fd68d5f0100n60h.html 前言--构造函数.析构函数的简单理解:1)构造函数---对象被创建时候调用的函数:2)析构函数 ...
- c++学习之对象和类——构造函数和析构函数
再认真理一遍~ 0.类 这里先来定义一个类,便于后面的理解.参考C++ Primer Plus class Stock { private: std::string company; long sha ...
- 基础学习:关于this在派生类构造函数中的理解
https://www.cnblogs.com/Bear-Study-Hard/archive/2006/01/09/313551.html 看了上面这篇文章有感,特做了个小样板,以加深对于this在 ...
- C++:派生类的构造函数和析构函数
4.2 派生类的构造函数和析构函数4.2.1 派生类构造函数和析构函数的执行顺序 通常情况下,当创建派生类对象时,首先执行基类的构造函数,随后再执行派生类的构造函数:当撤销派生类对象时,则先执行派生类 ...
- C++构造函数和析构函数顺序
构造函数 先看看构造函数的调用顺序规则,只要我们在平时编程的时候遵守这种约定,任何关于构造函数的调用问题都能解决:构造函数的调用顺序总是如下:1.基类构造函数.如果有多个基类,则构造函数的调用顺 ...
随机推荐
- sql点滴—mysql中查询表的信息
mysql中查询表的信息 查询mysql表字段信息的sql语句 SHOW DATABASES //列出 MySQL Server 数据库. SHOW TABLES [FROM db_name] //列 ...
- Python学习(七)面向对象 ——继承和多态
Python 类的继承和多态 Python 类的继承 在OOP(Object Oriented Programming)程序设计中,当我们定义一个class的时候,可以从某个现有的class 继承,新 ...
- 旋转的地球css3
css3果然博大精深: 1.代码里面还有用box-shadow制作椭圆形阴影的效果,厉害了!之前找了好久都没找到,今天给找到了 html: <section class="stage& ...
- Android常见UI组件之ListView(一)
使用ListView显示一个长的项列表 1.新建一个名为"BasicView5"的Android项目. 2.改动BasicView5.java文件.改动后的程序例如以下: pack ...
- linux添加磁盘空间
首先你要关掉系统,把分配的硬盘空间变大,或者重新建立一个虚拟硬盘(这时下面的就不是sda了,而是sdb1了).这两种方法都可行,我都试过了.其次用root用户登录到你的linux系统,查看你系统的分区 ...
- 2879: [Noi2012]美食节
Description CZ市为了欢迎全国各地的同学,特地举办了一场盛大的美食节.作为一个喜欢尝鲜的美食客,小M自然不愿意错过这场盛宴.他很快就尝遍了美食节所有的美食.然而,尝鲜的欲望是难以满足的.尽 ...
- 2.3.1 TextView(文本框)详解
http://www.runoob.com/w3cnote/android-tutorial-textview.html 1.基础属性详解: 通过下面这个简单的界面,我们来了解几个最基本的属性: 布局 ...
- numpy库数组拼接np.concatenate的用法
concatenate功能:数组拼接 函数定义:numpy.concatenate((a1, a2, ...), axis=0, out=None)
- Python2.7-struct模块
struct模块 处理二进制数据,与C语言交互,可以较为方便的对C语言的struct类型和python中的数据进行转换 主要是用于将int,char之类的C语言中基础数据pack至一个二进制流的字符串 ...
- Android 对BaseAdapter做优化处理
对于BaseAdapter相信大家都不陌生,都知道该怎样用.怎样显示数据.怎样尽可能的把每个item做的令自己满意.但问题来了:有些朋友会说我界面做的非常的漂亮,数据也显示的非常完美,但是问什么我的L ...