目录
一、为什么要继承?
面向对象程序设计中最重要的一个概念是继承。继承允许我们依据另一个类来定义一个类,这使得创建和维护一个应用程序变得更容易。这样做,也达到了重用代码功能和提高执行效率的效果。
当创建一个类时,您不需要重新编写新的数据成员和成员函数,只需指定新建的类继承了一个已有的类的成员即可。这个已有的类称为基类(父类),新建的类称为派生类(子类)。
二、三种继承方式
- public(公共继承):各个权限都不变,public还是public,protected还是protected;
- private(私有继承):public和protected都变成了private;
- protected(保护继承):public和protected都变成了protected。
继承方式/父类中的权限 public private protected public public × protected private private × private protected protected × protected
那么,private去哪了呢?没错,在类的访问权限中,private是它的子类也不能访问的,这就是它与protected的区别(若是不清楚访问权限可看C++ 封装、三种访问权限以及class与struct的区别),所以private权限的成员在明面上没有被继承,但是实际情况真的如此吗? 请看第三点。
三、继承的说明(注意点)
其实子类不管使用何种继承方式,它其实都把父类中所有的成员给继承了,只是由于这些成员在父类中的访问权限和继承的继承方式不一样,这些被继承下来的成员被编译器给屏蔽了,我们是找不到它的,但是我们可以去验证它的存在
#include<iostream>
using namespace std;
class Father {
public:
int m_Name;
private:
int m_Account;
protected:
int m_Age;
};
class Son : public Father {
};
int main() {
Son first;
cout << sizeof(first) << endl;
}
这一串代码中,Son是Father的子类 ,我们可以看到Son本身内部是没有成员的,但是它以public的方式继承了Father中的成员。
在Father中,有三个属性,根据访问权限可知,能被Son继承的只有public和protected权限,因此,Son中应当有两个int类型的成员,因此我们实例化的对象first应当占据8个字节的内存,因此sizeof的理论上的输出值应当是8,但是我们看看sizeof的实际输出情况:
居然是12!说明父类中的三个成员都被继承下来了,这就说明,在继承的时候,其实不论父类中的成员是何种权限,它都被子类完整的继承了,只是因为权限原因,它被编译器自动屏蔽了,我们在子类中没法找到它。
那么现在我们就又存在了一个问题:我实例化一个Son类型的对象,但是Son类中本来是没有成员的,需要继承Father,那Father和Son两个类的构造与析构函数的执行顺序是怎样的呢?
四、父类与子类的构造与析构函数的执行顺序
构造时:先父类的构造,再子类的构造。这个其实好理解,因为子类中的成员是继承自父类的,只有先调用父类的构造函数,子类才能知道自己应该继承了父类的哪些成员。
析构时:先调用子类的析构,再调用父类的析构,跟构造时正好相反。这个也好理解,如果编译器先调用的是父类的析构函数,那么子类是不是就有一段时间会失去模板?这自然是不可取的。(以上这些只是便于记忆,实际咋样我不知道)