C++学习笔记和总结
这段时间看了C++中类的继承和派生,这应该算是C++和C语言相比最主要的一个知识点了。不得不说类的功能是十分强大的,它定义了public,protected,private三种访问内部成员的访问权限,增加了程序的安全性和保护性。通过定义类的对象可以访问类的成员,但是定义对象是外部访问,只能访问类的公有成员,不能访问保护成员和私有成员。
类的继承和派生是相对来说的,派生类获得基类的已有特性叫继承,基类产生新类的过程叫派生。继承的过程包含三个方面:1、吸收基类成员,基类成员中除了构造函数和析构函数,其他所有函数全部被接收(基类的构造函数和析构函数不能被派生类继承);2、修改基类成员,(1)设置派生类声明中的继承方式,改变访问属性;(2)声明和基类中数据或函数同名的成员,覆盖相应的数据或函数;3、添加新成员。
派生类的声明形式: class 派生类名:继承方式1 类名1,继承方式2 类名2,...,继承方式n 类名n
{
派生类的成员声明;
}
基类的构造函数和析构函数派生类是不能继承的,如果派生类需要对新成员初始化或者进行特定的清理工作,就需要自己定义构造函数和析构函数了。从基类继承的成员的初始化仍可通过基类的构造函数来完成。使用派生类的对象以前需要对它的数据成员进行初始化赋值。派生类的数据成员包括从基类继承来的数据成员和派生类新增的数据成员,还可能包括其他类的对象作为其数据成员,包括其他类的对象时实际上还间接包括了这些对象的数据成员。因此,对派生类初始化时就需要对基类的数据成员、派生类新增数据成员和内嵌的其他类对象的数据成员进行初始化。
基类的构造函数若有参数,则派生类必须定义构造函数,将传入的参数再传递给基类的构造函数,对基类进行初始化。若基类没有定义构造函数,则派生类也可以不定义构造函数,都使用默认构造函数,对于派生类的新增数据成员可以通过其他的公有函数成员来初始化。而如果基类同时定义了默认构造函数和带参数的构造函数,那么在派生类的构造函数中可以给出基类名及其参数表,也可以不显式给出。
构造派生类的对象调用构造函数时的处理顺序是:1.首先调用基类的构造函数,若有多个基类,调用顺序按照它们在派生类声明时从左到右出现的顺序;2.如果有内嵌对象成员,则调用内嵌对象成员的构造函数,若为多个内嵌对象,则按照它们在派生类中声明的顺序调用,如果无内嵌对象则跳过这一步;3.调用派生类构造函数中的语句。
程序说明:
#include<iostream>
using namespace std;
class Base1
{
public:
Base1(){cout<<"Base1 construct"<<endl;}
~Base1(){cout<<"Base1 desteruct"<<endl;}
};
class Base2
{
public:
Base2(int x){cout<<"Base2 construct"<<x<<endl;}
~Base2(){cout<<"Base2 desteruct"<<endl;}
};
class Base3
{
public:
Base3(int y){cout<<"Base3 construct"<<y<<endl;}
~Base3(){cout<<"Base3 desteruct"<<endl;}
};
class Child :public Base2,public Base1,public Base3
{
public:
Child(int i,int j,int k,int m):Base2(i),b3(j),b2(k),Base3(m){};
private:
Base1 b1;
Base3 b3;
Base2 b2;
};
int main()
{
Child child(3,4,5,6);
return 0;
}
程序运行结果如图所示,由此可见声明派生类的对象时调用派生类的构造函数,执行时先调用基类的构造函数,调用顺序为在派生类声明时它们从左到右出现的顺序(base2,base1 base3);然后调用内嵌对象成员的构造函数,调用顺序为它们在派生类中声明的顺序(base1,base3,base2)。
析构函数执行时所有成员或对象的清理顺序与构造函数的构造顺序刚好完全相反。