C++有三大特征,封装、继承与多态,在本篇文章中,与大家来聊一聊继承。
继承的本质就是代码的复用。简单的说,继承是指一个对象直接使用另一对象的属性和方法。
C++中的继承关系就好比现实生活中的父子关系,继承一笔财产比白手起家要容易得多,原始类称为基类,继承类称为派生类,它们是类似于父亲和儿子的关系,所以也分别叫父类和子类。而子类又可以当成父类,被另外的类继承。
1.在C++中派生来(子类)继承基类(父类)的什么?
1)、派生类继承了基类中除构造函数与析构函数外的所有成员。
2)、派生类还继承了基类的作用域。
2.继承的写法是什么?
类标识 派生类名程 :继承方式 基类名称
class Base
{};
class Derived:public Base
{};
3.继承与派生的关系。
继承是面向对象语言的一个重要机制,通过继承可以在一个一般类的基础上建立新类,被继承的类称为基类,
在基类上建立的新类称为派生类。子类继承了父类,父类派生了子类。他们之间的关系是对立共存的。
4.派生类的内存布局。
派生类中成员是如何在内存中布局的呢?我们以如下代码为例分析。
class Base
{
public:
Base(int a):ma(a){}
protected:
int ma;
};
class Derived:public Base
{
public:
Derived(int b):mb(b),Base(b){}
private:
int mb;
};
在上面的代码中Derived类继承了Base的成员,Derived类中就有了ma成员变量,但是ma与mb的存储顺序是怎样呢?
基类包含在派生类中,派生类的成员在基类成员之后。
5.派生对象的构造、析构方式和顺序。
每一个派生类的构造生成的时候都是在基类的基础生成的,也就是说生成一个派生类就要生成一个基类。但是派生类与基类生成时它们构造的顺序是什么呢?
1)、对于派生类对象的构造,系统先调用基类的构造,然后再调用派生类的构造。
2)、对于派生类对象的析构,系统先调用派生类的析构,然后再调用基类的析构。
#include<iostream>
class Base
{
public:
Base(int a):ma(a)
{
std::cout<<"Base::Base() "<<std::endl;
}
~Base()
{
std::cout<<"Base::~Base() "<<std::endl;
}
protected:
int ma;
};
class Derived:public Base
{
public:
Derived(int b):mb(b),Base(b)
{
std::cout<<"Derived::Derived() "<<std::endl;
}
~Derived()
{
std::cout<<"Derived::~Derived() "<<std::endl;
}
private:
int mb;
};
int main()
{
Derived d(10);
return 0;
}
由上面的代码可以看出,派生对象构造时的构造函数与析构函数的调用顺序如上文所述。
6.基类中不同访问限定符下的成员以不同的继承方式继承后在派生类中的访问限定。
//横向为基类成员在基类中的访问限定方式,纵向为继承方式
继承方式\基类成员 | public | protecred | private |
public | public | protected | 不可访问 |
protected | protected | protected | 不可访问 |
private | private | private | 不可访问 |
7.当基类或派生类指针或引用相互指向或引用问题。
C++标准允许基类指针或引用指向或引用派生类对象,反之则不允许。
以上面的基类与派生类代码为例。
int main()
{
// Derived* pd = new Base(10);//派生类指针指向基类对象 error
Base* pb = new Derived(10);//基类指针指向派生类对象 ok
Base b(10);
Derived d(20);
// Derived& rd = b; //派生类引用引用基类对象 erroe
Base& rb = d; //基类引用引用派生类对象 ok
return 0;
}