详细介绍:C++篇(11)继承
一、继承的概念及定义
1.1 继承的概念
继承机制是面向对象程序设计使代码可以复用的最重要的手段,它允许我们在保持原有类的基础上进行拓展,增加方法(成员函数)和属性(成员变量),从而产生新的类,称为派生类。继承是类设计层次的复用。
比如下面,我们把公共的成员都放到Person类当中,Student和Teacher类都继承了Person,就可以复用这些成员。
#define _CRT_SECURE_NO_WARNINGS 1
#include
using namespace std;
class Person
{
public:
void identity()
{
cout << "void identity()" << _name << endl;
}
protected:
string _name = "张三"; //姓名
string _address; //地址
string _tel; //电话
int _age = 18; //年龄
};
class Student :public Person
{
public:
void study()
{
//...
}
protected:
int _stuid; //学号
};
class Teacher :public Person
{
public:
void teaching()
{
//...
}
protected:
string _title; //职称
};
int main()
{
Student s;
Teacher t;
s.identity();
t.identity();
return 0;
}
1.2 继承的定义
在上面的代码中,我们可以看到Person是基类(也称为父类),Student是派生类(也称为子类)
基类的private成员在派生类中都是不可见的,这里的不可见是指基类的私有成员还是被继承到了派生类对象中,但是语法上限制派生类对象不管在类里面还是类外面都不能去访问。如果基类成员不想在类外面直接被访问,但是需要在派生类中访问,就定义为protected。
在实际运用中一般都是public继承,几乎很少使用protected/private继承,因为protected/private继承下来的成员都只能在派生类里面使用,实际中拓展维护性不强。
1.3 继承类模板
当基类是类模板时,需要指定一下类域,否则编译报错(如下图所示)

因为Stack<int>在实例化时,也实例化了vector<int>,但是模板是按需实例化,push_back成员函数并未实例化,所以编译器找不到。
正确代码如下:
#include
#include
namespace bit
{
template
class Stack : public std::vector
{
public:
void push(const T& x)
{
vector::push_back(x);
}
};
}
int main()
{
bit::Stack st;
st.push(1);
st.push(2);
st.push(3);
return 0;
}
二、基类与派生类之间的转换
通常情况下,我们把一个类型的对象赋值给另一个类型的指针或者引用时,存在类型转换,中间会产生临时对象,所以需要加const。而public继承中,就是一个特殊的例外,派生类对象可以赋值给基类的指针 / 基类的引用,并且不需要加const。这里的指针和引用绑定的是派生类对象中的基类部分,如下图所示:

派生类对象可以赋值给基类对象,是通过基类的拷贝构造函数或者赋值重载函数完成的。这个过程就像是派生类自己定义部分成员切掉了一样,所以也被叫做切割或者切片。但是基类对象不能赋值给派生类对象。
三、继承中的作用域
在继承体系中,基类和派生类都有独立的作用域。因此,派生类和基类中是会出现同名成员的,而派生类会屏蔽基类对同名成员的直接访问,这种情况叫隐藏(在派生类成员函数中,可以使用 基类::基类成员 显示访问)。在实际中,继承体系里面最好不要定义同名成员。
注意:如果是成员函数的隐藏,
浙公网安备 33010602011771号