不要否定过去,也不要用过去牵扯未来。不是因为有希望才去努力,而是努力了,才能看到希望。💓💓💓
目录
✨说在前面
亲爱的读者们大家好!💖💖💖,我们又见面了,上一篇文章我给大家详细而详细地讲解了C++模板进阶部分的知识。如果大家没有掌握好相关的知识,上一篇篇文章讲解地很详细,可以再回去看看,复习一下,再进入今天的内容。
我们之前给大家讲解模板的内容,只不过那是初阶,我们今天给大家讲解C++中面向对象的一大特点:继承。如果大家准备好了,那就接着往下看吧~
👇👇👇
💘💘💘知识连线时刻(直接点击即可)🎉🎉🎉复习回顾🎉🎉🎉
博主主页传送门:愿天垂怜的博客
🍋知识点一:继承的概念及定义
•🌰1.继承的概念
继承(inheritance)机制是面向对象程序设计使代码可以复用的最重要的手段,它允许我们在保持原有类特性的基础上进行扩展,增加方法(成员函数)和属性(成员变量),这样产生新的类,称派生类。继承呈现了面向对象程序设计的层次结构,体现了由简单到复杂的认知过程。以前我们接触的函数层次的复用,继承是类设计层次的复用。
下面我们看到没有继承之前我们设计了两个类Student和Teacher,Student和Teacher都有姓名/地址/电话/年龄等成员变量,都有identity身份认证的成员函数,设计到两个类里面就是冗余的。当然他们也有一些不同的成员变量和函数,比如老师独有成员变量是职称,学生的独有成员变量是学号;学生的独有成员函数是学习,老师的独有成员函数是授课。
class Person
{
public:
//进入校园/图书馆/实验室刷二维码等身份认证
void identity()
{
cout << "void identity()" << " " << _name << endl;
}
protected:
string _name = "crayon"; //姓名
string _address; //地址
string _tel; //电话
private:
int _age = 18; //年龄
};
class Student : public Person
{
public:
//学习
void study()
{
//...
}
protected:
int _stuid; //学号
};
class Teacher : public Person
{
public:
//授课
void teaching()
{
//...
}
protected:
string title; //职称
};
下面我们公共的成员都放到Person类中,Student和teacher都继承Person,就可以复用这些成员,就不需要重复定义了,省去了许多麻烦。
•🌰2.继承定义
🔥定义格式
下面我们看到Person是基类,也称作父类。Student是派生类,也称作子类。(因为翻译的原因,所以既叫基类/派生类,也叫父类/子类)。


🔥继承基类成员访问方式的变化
类成员/继承方式 | public继承 | protected继承 | private继承 |
基类的public成员 | 派生类的public成员 | 派生类的protected成员 | 派生类的private成员 |
基类的protected成员 | 派生类的protected成员 | 派生类的protected成员 | 派生类的private成员 |
基类的private成员 | 在派生类中不可见 | 在派生类中不可见 | 在派生类中不可见 |
1.基类private成员在派生类中无论以什么方式继承都是不可见的。这里的不可见是指基类的私有成员还是被继承到了派生类对象中,但是语法上限制派生类对象不管在类里面还是类外面都不能去访问它。
2.基类private成员在派生类中是不能被访问,如果基类成员不想在类外直接被访问,但需要在派生类中能访问,就定义为protected。可以看出保护成员限定符是因继承才出现的。
3.实际上面的表格我们进行一下总结会发现,基类的私有成员在派生类都是不可见。基类的其他成员在派生类的访问方式 = Min(成员在基类的访问限定符,继承方式),public > protected >private。
4.使用关键字class时默认的继承方式是private,使用struct时默认的继承方式是public,不过最好显式的写出继承方式。
5.在实际运用中一般使用都是public继承,几乎很少使用protetced/private继承,也不提倡使用protetced/private继承,因为protetced/private继承下来的成员都只能在派生类的类里面使用,实际中扩展维护性不强。
•🌰3.继承类模板
在C++中,类模板是一种允许我们定义通用类的方法,这样我们可以用不同的类型来实例化这个类。继承类模板则是指在类模板的基础上创建新的类模板,以复用和扩展原有类模板的功能。
例1:
namespace bit
{
//stack和vector的关系,既复合is-a,也复合has_a
template<class T>
class stack : public vector<T>
{
public:
void push(const T& x)
{
vector<T>::push_back(x);
}
void pop()
{
vector<T>::pop_back();
}
const T& top()
{
return vector<T>::back();
}
bool empty()
{
return vector<T>::empty();
}
};
}
int main()
{
bit::stack<int> st;
st.push(1);
st.push(2);
st.push(3);
st.push(4);
st.push(5);
while (!st.empty())
{
cout << st.top() << endl;
st.pop();
}
return 0;
}
例2:
amespace bit
{
//stack和vector的关系,既复合is-a,也复合has_a
template<class T>
class stack : public list<T>
{
public:
void push(const T& x)
{
list<T>::push_back(x);
}
void pop()
{
list<T>::pop_back();
}
const T& top()
{
return list<T>::back();
}
bool empty()
{
return list<T>::empty();
}
};
}
int main()
{
bit::stack<int> st;//仅仅实例化了构造函数
st.push(1);
st.push(2);
st.push(3);
st.push(4);
st.push(5);
while (!st.empty())
{
cout << st.top() << endl;
st.pop();
}
return 0;
}
这里我们要注意,模板是按需实例化的,即用到的函数才会实例化。在VS2022中,未被调用的类内部的函数中有依赖模板