cf活动-C++|深化了解派生类的结构、析构函数及结构、析构次序

派生类的新增数据成员需求界说结构函数或隐式运用默许的结构函数来初始化,这是没有问题的,但关于承继过来的基类的数据成员(包括目标成员)怎么初始化呢?

1 是承继基类的结构函数(一个或多个)仍是在派生类结构函数中调用基类的结构函数?C++编译器的做法是不承继,而是在派生类中运用初始化列表来调用基类的结构函数(由于派生类无法访问基类的私有数据成员,也就无法在派生类结构函数体中来做初始化);

2 假如基类中仅仅界说了一个无参的结构函数,能够不运用初始化列表显式调用基类的结构函数,C++编译器会隐式地调用这个无参的结构函数或缺省的结构函数;

3 假如数据成员中有目标成员时,目标成员的声明是无法在声明时一起附加结构信息的,也需求隐式或显式地调用结构函数来初始化数据成员。

派生类的结构函数需求做的作业包括:运用传递给派生类的参数,调用基类的结构函数和内嵌目标成员的结构函数来初始化它们的数据成员,再增加新句子初始化派生类新成员。

派生类结构函数的语法方式为:

派生类名::派生类名(参数表):基类名1(参数表1),...基类名m(参数名m),
内嵌目标名(内嵌目标参数表1),...,内嵌目标名n(内嵌目标参数表n)
{
初始化派生类新成员的句子;
}

派生类的结构函数名相同也要与类cf活动-C++|深化了解派生类的结构、析构函数及结构、析构次序名相同。结构函数参数表要给出初始化基类数据成员、新增数据成员和内嵌目标的数据成员的一切参数。在给出一切这些参数今后就要像上面那样指明一切要初始化的基类名及其参数表,还有内嵌目标名及其参数表。各个基类名和内嵌目标名能够以任何的次序排列。

结构派生类的目标调用结构函数时的处理次序是:

1 假如基类有内嵌目标成员,则调用内嵌目标成员的结构函数,若为多个内嵌目标,则依照它们在类中声明的次序调用,假如无内嵌目标则越过这一步;

2 调用基类的结构函数,若有多个基类,调用次序依照它们在派生类声明时从左到右呈现的次序;

3 假如派生类有内嵌目标成员,则调用内嵌目标成员的结构函数,若为多个内嵌目标,则依照它们在派生类中声明的次序调用,假如无内嵌目标则越过这一步;

4 调用派生类结构函数中的句子。

这儿需求阐明的是cf活动-C++|深化了解派生类的结构、析构函数及结构、析构次序,基类和内嵌目标成员的结构函数的调用次序和它们在派生类结构函数中呈现的次序无关。

以下是一个简略实例:

#include 
#include
using namespace std;
class BaseMember
{
public:
BaseMember(){cout<<"BaseMember constructor is called\n";}
};
class Base
{
public:
//基类结构函数,初始化成员变量
Base(int n, string na, char se):num(n),name(na),sex(se)
{cout<<"Base Constructor is called"<
~Base(){cout<<"~Base"<
void display1(){cout<<<'\t'<<<'\t'<<<'\t'; }
protected:
int num;
string name;
char sex;
BaseMember baseMember;
};

class Derived:public Base
{
public:
//派生类调用基类结构函数
Derived(int n, string na, char se, int n_m, string na_m, char se_m, int a, string add):Base(n,na,se),monitor(n_m,na_m,se_m)
{age = a; addr = add;cout<<"Derived Constructor is called"<
~Derived(){cout<<"~Derived"<
void display2(){display1();cout<<<'\t'<<
void showmonitor()
{cout<<"Monitor is:"<
monitor.display1();
cout<
private:
int age;
string addr;
Base monitor;//包括子目标
};
int main()
{
Derived s(200, "ace", 'M', 11, "HH", 'M', 26, "Shanghai");
s.display2();
s.showmonitor();
cin.ignore();
return 0;
}
/*输出成果(后边的//是对成果的解说部分)
BaseMember constructor is called // ①调用基类内嵌目标的结构函数
Base Constructor is called // ②调用基妈妈的朋类的结构函数
BaseMember constructor is called//③ 派生类内嵌目标调用其内嵌目标的结构函数
Base Constructor is called//③ 派生类内嵌目标调用其结构函数
Derived Constructor is called//④ 调用派生类的结构函数
200 ace M 26 Shanghai //目标成员函数调用
Monitor is: //目标成员函数调用
11 HH M
*/

或许我们觉得上述派生类结构函数的语法方式过分杂乱,但其实结构函数也不是有必要写这么杂乱。假定一个类承继自多个基类,即为多承继时,关于那些结构函数有参数的基类就有必要显式给出基类名及其参数表,而关于那些运用默许结构函数的基类没有必要给出基类名及其参数表,同理内嵌目标的结构函数若有参数也有必要给出内嵌目标名及其参数表,若运用默许结构函数也没有必要给出内嵌目标名及其参数表。试想,假如派生类只要一个基类,并且有默许结构函数,没有内嵌目标或许能够运用其他公有函数成员初始化内嵌目标,那么后边的基类名和内嵌目标名就都不需求了,是不是方式就很简略了?

需求再次着重的是,基类的结构函数若有参数,则派生类有必要显式地在结构函数的初始化列表中调用基类的结构函数,将传入的参数再传递给基类的结构函数,对基类进行初始化。若基类没有界说结构函数,则派生类也能够不界说结构函数,都运用默许结构函数,关于派生类的新增数据成员能够经过其他的公有函数成员来初始化。而假如基类一起界说了默许结构函数和带参数的结构函数,那么在派生类的结构函数中能够给出基类名及其参数表,也能够不显式给出。

正如派生类不能承继基类的结构函数,派生类也不能承继基类的析构函数,但相关于结构函数,析构函数是不能重载的,也便是每一个类只要一个析构函数,这样,编译器处理起来就简略了,派生类的整理作业由派生本身析构函数担任,基cf活动-C++|深化了解派生类的结构、析构函数及结构、析构次序类的整理作业由基类析构函数担任。

派生类的析构函数一般只需求在其函数体中整理新增成员就能够了,关于承继的基类成员和派生类内嵌目标成员的整理,则一般由体系主动调用基类和目标成员的析构函数来完结。析构函数履行时对一切成员或目标的整理次序与结构函数的结构次序刚好彻底相反:

1 履行析构函数句子整理派生类的新增成员;

2 调用派生类中内嵌目标成员(假如有)所属类的析构函数整理派生类内嵌目标成员,各个目标成员的整理次序与其在结构函数中的结构次序相反;

3 调用基类的析构函数整理承继的基类成员,假如是多承继则各个基类的整理次序也与其在结构函数中的结构次序相反。

4 调用基类内嵌目标成员(假如有)所属类的析构函数整理基类内嵌目标成员,各个目标成员的整理次序与其在结构函数中的结构次序相反;

-End-