【一天一篇CPP】派生类的构造函数和析构函数

来源:互联网 发布:杭州知乐 编辑:程序博客网 时间:2024/05/19 20:57

1.基类的构造函数是不能继承的,在声明派生类时,派生类并没有把基类的构造函数继承过来,但是可以通过一种显式的声明来调用基类的构造函数。

对于析构函数,系统会自动调用基类的析构函数,详细看下面的 “3注意点”。

2.构造函数调用的例子:

#include <iostream>#include <string>using namespace std;class Student{public:Student (int n, string nam,char s): num (n), name (nam),sex(s){};public:int num;string name;char sex;};class Student1: public Student{public:Student1(int n,string nam, char s,int a,string ad):Student(n,nam,s){age = a;addr = ad;//当然也可以在上面写Student(n,nam,s),age(a),addr(ad)}public:int age;string addr;};int main(){Student1 stud(1,"C雄",'m',20,"school");cout << stud.num << "  " << stud.name << "  "  << stud.addr<<endl;return 0;}

3.注意点:

A 派生类是先调用基类的构造函数,再构造派生类增加的成员。

B 对象释放时,基类的析构函数是自动被系统调用的,不用用户操刀。系统先调用派生类的析构函数,【然后是子对象的析构函数,】最后自动调用基类的析构函数。


4.有子对象的派生类的构造函数【子对象:对象的对象,它是类的对象,但充当另一个类的数据成员,如public: string str1;,而string本身是一个类】

如何为子对象构造呢,一个例子


#include <iostream>#include <string>using namespace std;class Student{public:Student (int n, string nam): num (n), name (nam){};public:int num;string name;};class Student1: public Student{public:Student1(int n,string nam, int n1,string nam1, int a,string ad):Student(n,nam),monitor(n1,nam1){age = a;addr = ad;//当然也可以在上面写Student(n,nam,s),age(a),addr(ad)}public:Student monitor;int age;string addr;};int main(){Student1 stud(1,"C雄",2,"B雄",20,"school");cout << stud.num << "  " << stud.name << "  "  << stud.addr<< "  " << stud.monitor.name<< endl;return 0;}


这个例子中,派生类的构造函数包括三个部分:

A 通过基类的构造函数对基类成员进行初始化

B 通过子对象的构造函数对子对象数据成员进行初始化

C 对派生类增加的数据成员的初始化


形式总结:

派生类构造函数名( 总参数列表 ) : 基类构造函数名( 参数列表 ) , 子对象名【注意不是子对象的类名】( 参数列表 )

{派生类中新增加的数据成员的初始化,这些内容写到上一行也可以,请参照上门第一个例子}

其中若三者都写在第一行,三者的书写顺序可以改变,但是无聊如何改变,调用顺序仍然为:基类的构造函数、子对象的构造函数、新增成员的构造。


5.多层派生【派生完再派生,不是多继承的意思】和构造函数和析构函数

多层派生时的构造函数:


#include <iostream>#include <string>using namespace std;class Student{public:Student (int n, string nam): num (n), name (nam){};int num;string name;};class Student1 : public Student{public:Student1(int n,string nam,  int a):Student(n,nam){age = a;}int age;};class Student2 : public Student1{public:Student2(int n, char nam[10], int a, float s): Student1(n,nam,a)//这里突然把string ...改为 char ...[10]了,但是因为字符指针是可以赋值给string的,所以没问题{score = s;}float score;};int main(){Student2 std2(10,"C雄",20,80);cout << std2.num <<endl;cout << std2.name <<endl;cout << std2.age <<endl;cout << std2.score <<endl;return 0;}

注意:

A 不要列出每一层派生类的构造函数,只要写出上一层派生类的构造函数即可。

B 系统会默认先构造最源头的基类,再初始化更分支的基类,最后是它自己的成员。【析构函数则相反


6.派生类的构造函数的特殊形式

A 假如派生类   没有用户定义的构造函数   或   构造函数中没有对基类的构造函数进行显式调用   ,那么意味着系统默认隐含调用基类的默认构造函数【当然这个默认构造函数可能是系统生成的,也可能是用户定义的,系统只会在用户没有定义构造函数的时候生成默认构造函数,当不能生成则派生类构造出错】。例子如下:

#include <iostream>#include <string>using namespace std;class Student{public:Student (int n = 50, string nam = "C雄"): num (n), name (nam){};int num;string name;};class Student1 : public Student{public:Student1( int a){age = a;}int age;};int main(){Student1 std1(20);cout << std1.num <<endl;cout << std1.name <<endl;cout << std1.age <<endl;return 0;}//输出为50回车C雄回车20回车
在这个例子中若派生类自己增加的age变量不需要初始化,则可以省略它的构造函数!!

B 基类有且只有定义了带参数的构造函数【系统不会生成默认构造函数】,则在派生类中不能省略构造函数,且必须显式地调用基类的构造函数!【假如基类既有带参数的构造函数,又有没有参数的默认构造函数,则派生类的构造函数可以显式调用也可以不调用基类的构造函数】


C 以上A B 两点对基类适用,对子对象其实也适用。


原创粉丝点击