C++的知识分享程序员C++

10. C++基类和派生类构造函数和析构函数

2019-04-04  本文已影响17人  飞扬code

10.1 构造函数

类的构造函数不能被继承。
因为即使继承了,它的名字和派生类的名字也不一样,不能成为派生类的构造函数,当然更不能成为普通的成员函数。

在设计派生类时,对继承过来的成员变量的初始化工作也要由派生类的构造函数完成,但是大部分基类都有 private 属性的成员变量,它们在派生类中无法访问,更不能使用派生类的构造函数来初始化。

解决这个问题的思路是:在派生类的构造函数中调用基类的构造函数。

#include<iostream>
using namespace std;

//基类Person
class Person{
protected:
    char *name;
    int age;
public:
    Person(char*, int);
};
Person::Person(char *name, int age): name(name), age(age){}

//派生类Student
class Student: public Person{
private:
    float score;
public:
    Student(char *name, int age, float score);
    void display();
};

//Person(name, age)就是调用基类的构造函数
Student::Student(char *name, int age, float score): Person(name, age), score(score){ }

void Student::display(){
    cout<<this->name<<"的年龄是"<<this->age<<",成绩是"<<this->score<<"。"<<endl;
}

int main(){
    Student stu("呵呵", 18, 78.0);
    stu.display();
    return 0;
}
image.png

构造函数调用顺序
基类构造函数总是被优先调用,这说明创建派生类对象时,会先调用基类构造函数,再调用派生类构造函数,如果继承关系有好多层,例如:
A --> B --> C
那么创建 C 类对象时构造函数的执行顺序为:
A类构造函数 --> B类构造函数 --> C类构造函数

构造函数的调用顺序是按照继承的层次自顶向下、从基类再到派生类的。
注意:派生类构造函数中只能调用直接基类的构造函数,不能调用间接基类的。


10.2 基类构造函数调用规则

事实上,通过派生类创建对象时必须要调用基类的构造函数,这是语法规定。
例如一个失败的例子:

#include <iostream>
using namespace std;

//基类Person
class Person{
public:
    Person(); //基类默认构造函数
    Person(char *name, int age);
protected:
    char *name;
    int age;
};

Person::Person(): name("豆豆"), age(0){ }
Person::Person(char *name, int age): name(name), age(age){}

//派生类Student
class Student: public Person{
public:
    Student();
    Student(char*, int, float);
public:
    void display();
private:
    float score;
};

Student::Student(): score(0.0){ } //派生类默认构造函数
Student::Student(char *name, int age, float score): Person(name, age), score(score){ }

void Student::display(){
    cout<<this->name<<"的年龄是"<<this->age<<",成绩是"<<this->score<<"。"<<endl;
}

int main(){
    Student stu1;
    stu1.display();
    Student stu2("哈哈", 16, 80.0);
    stu2.display();
    return 0;
}

image.png

10.3 析构函数

和构造函数类似,析构函数也不能被继承。
与构造函数不同的是,在派生类的析构函数中不用显式地调用基类的析构函数,
因为每个类只有一个析构函数,编译器知道如何选择,无需程序员干涉。
另外析构函数的执行顺序和构造函数的执行顺序也刚好相反:
1、创建派生类对象时,构造函数的执行顺序和继承顺序相同,即先执行基类构造函数,再执行派生类构造函数。
2、而销毁派生类对象时,析构函数的执行顺序和继承顺序相反,即先执行派生类析构函数,再执行基类析构函数。

#include <iostream>
using namespace std;
class A{
public:
    A(){cout<<"A constructor"<<endl;}
    ~A(){cout<<"A destructor"<<endl;}
};
class B: public A{
public:
    B(){cout<<"B constructor"<<endl;}
    ~B(){cout<<"B destructor"<<endl;}
};
class C: public B{
public:
    C(){cout<<"C constructor"<<endl;}
    ~C(){cout<<"C destructor"<<endl;}
};
int main(){
    C test;
    return 0;
}
image.png
上一篇下一篇

猜你喜欢

热点阅读