继承(加深)-构造函数调用顺序与函数重定义
来源:互联网 发布:镜像站搭建 知乎 编辑:程序博客网 时间:2024/05/22 11:31
一、派生类的构造函数与析构函数
从基类派生子类时,基类的构造函数不能继承到派生类中,因此我们在定义派生类的构造函数时除了对自己的数据成员进行初始化外,还必须负责调用基类构造函数。如果派生类中有子对象,还应包含对子对象初始化的构造函数。
派生类构造函数一般的执行顺序为:
(1)最先调用基类的构造函数,多个基类则按派生类声明时列出的次序,从左到右调用,而不是初始化列表中的次序。
(2)再调用对象成员(子对象)的构造函数,按类声明中对象成员出现的次序调用,而不是初始化列表中的次序。
(3)最后执行派生类的构造函数。
下面我们看一段程序:
#include<iostream>using namespace std;class A{public:A(){cout << "A Constructor1" << endl;}A(int i){x1 = i;cout << "A Constructor2" << endl;}void displaya(){cout << "x1=" << x1 << endl;}private:int x1;};class B :public A //若为多继承,按从左到右的顺序调用{public:B(){cout << "B Constructor1" << endl;}B(int i):A(i + 10){x2 = i;cout << "B Constructor2" << endl;}void displayb(){displaya();cout << "x2=" << x2 << endl;}private:int x2;};int main(){B b(2);b.displayb();system("pause");return 0;}
运行结果为:
上述程序中,类B是类A的派生类,该成员初始化列表的顺序是:先是基类A的构造函数,再是派生类B中子对象的构造函数,最后是B的构造函数。
如果类中包含对象成员呢?我们看看下面的程序:
class A{public:A(){cout << "class A" << endl;}};class B{public:B(){cout << "class B" << endl;}};class C{A a;public:C(){cout << "class C" << endl;}};class D :public C{B b;public:D(){cout << "class D" << endl;}};int main(){D d;system("pause");return 0;}
运行结果如下:
可以看出:
类C派生出类D,但类C包含一个类A的对象a,类D中包含一个类B的对象b,所以语句“D d”,先执行基类C中对象a的构造函数,再执行基类C的构造函数,接着是D中对象b的构造函数,最后执行类D的构造函数。
析构函数,其顺序与执行构造函数时的顺序正好相反。即次序如下:
(1)最先执行派生类的析构函数
(2)再调用对象成员(子对象)的析构函数,按类声明中对象成员出现的逆序调用,而不是初始化列表中的次序。
(3)最后调用基类的析构函数,多个基类则按派生类声明时列出的逆序(从右到左)调用。
二、继承成员的重定义
继承成员的重定义是指重新修改继承成员函数的实现。
我们先来看一段代码:
class A{int i;public:void set(int x){i = x;}void disp(){cout << "i=" << i << endl;}};class B{int j;public:void set(int y){j = y;}void disp(){cout << "j=" << j << endl;}};int main(){A a;B b;a.set(1); //调用类A的set函数a.disp();b.set(2); //调用类B的set函数b.disp();system("pause");return 0;}
运行结果为:
这是因为如果在派生类中增加一个函数原型与继承成员函数一模一样的成员函数,则该函数实现的函数体是对继承成员函数的重定义。
如果一个派生类的对象调用这个函数,首先在派生类中查找是否有该函数的定义,有则调用派生类中成员函数,否则才在所有的祖先类中查找。
三、友元关系不能继承
友元关系不能继承,也就是说基类友元不能访问子类私有和保护成员。除非在子类中也声明为友元。
四、静态成员数据
基类定义了static成员,则整个继承体系里面只有一个这样的成员。无论派生出多少个子类,都只有 一个static成员实例。
我们来看一个例子:
class Person{public:Person(){++_count;}protected:string _name;public:static int _count;};int Person::_count = 0;class Student :public Person{protected:int _num;};void TestPerson(){Person p;Student s1;Student s2;Student s3;cout << "人数:" << Person::_count << endl;Student::_count = 0;cout << "人数:" << Person::_count << endl;}int main(){TestPerson();system("pause");return 0;}
这就可以看出来对象共用一个静态成员。
- 继承(加深)-构造函数调用顺序与函数重定义
- C++继承构造函数调用顺序问题
- C++多继承构造函数调用顺序
- C++继承中构造函数调用顺序
- 继承中的构造函数调用顺序
- 继承中的构造函数调用顺序
- java继承的构造函数调用顺序
- 继承与派生,多继承,函数重载,构造函数调用顺序
- scala 类定义构造函数与继承
- 继承和构造函数析构函数调用顺序
- C++中多个类继承时构造函数与析构函数的调用顺序
- 构造函数调用顺序
- 构造函数调用顺序
- 构造函数调用顺序
- 构造函数调用顺序
- 继承与构造函数的调用
- C#继承与构造函数的调用
- 继承与派生,多继承,函数重载,构造函数调用顺序 静态多态和动态多态
- 第14章 类型信息
- 《伸手系列》第二集-oracle数据库“灾难性”数据恢复-(一)
- 如何利用**.ini配置文件获取MySQL连接信息
- JS设计模式-单例模式
- 在laravel中大家有没有遇到多个应用中数据库连接错乱问题?
- 继承(加深)-构造函数调用顺序与函数重定义
- sax生成xml文件
- 官网链接下载QT5 Creator
- 论文-基于椭球你和的三轴磁传感器误差补偿方法---第一个矩阵的解析
- Java9新特性调研
- linux 学习系列-Linux yum 命令
- Android开发打开指定QQ,申请加入QQ群,打开微信
- ThinkPHP之add、save无法添加、修改的解决方案
- MFC中注册WNDCLASS样式并建立窗口