一、多态
相同的代码、实现不同的功能
1.前提
1.类之间有继承关系
2.父类中有虚函数
3.父类的指针指向子类的对象
2.函数重写
1.发生在继承之间
2.父类中有虚函数
3.子类中对父类的虚函数重新实现
3.虚函数
1.在函数头前加上virtual
2.只要基类中的函数是虚函数,后面所有派生类中的该函数都是虚函数
3.如果在派生类中对基类中的虚函数进行了重新定义,该行为被称为函数重写
4.如果父类指针,指向子类的对象,可以调用出子类重写后的虚函数
5.只要类中存在虚函数,类中就会提供一个虚指针和虚函数表,(虚指针指向虚函数表)
1.虚函数表:用于保存所有虚函数的入口地址,只要类中有虚函数就会有一张对应的虚函数表
2.虚函数表的特点,会根据继承关系不断更新
3.虚指针:存放在类中的起始地址上,指向类的虚函数表,虚指针只有一个子类的虚指针是从父类中继承下来的
4.静态多态和动态多态
静态多态(编译时多态):函数重载 ------>在编译阶段中就已经区分不同的函数了
动态多态(运行时多态):基于继承的多态 ------>在代码运行时完成对不同功能的区分
二、纯虚函数
1.虚函数:在函数头前面加上virtual关键字
2.纯虚函数:在函数头前面加上virtual关键字,并且没有函数体直接=0
格式:virtual 返回值 函数名(参数列表)=0;
三、抽象类
1.包含纯虚函数的类就是抽象类
2.抽象类不允许实例化对象,只表示一个公共的属性
3.如果父类中包含纯虚函数,并且子类中没有对该纯虚函数重写,那么子类也是一个抽象类
四、模板
1.模板函数
template <typename T> //T就是一个模板,可以是任意类型
template:定义模板的关键字
<typename T>:模板提供的数据类型
2.模板函数的实现
2.1自动推导模板类型
模板只对紧跟在后面的第一行代码有效,如果后面还想定义模板函数需要重新定义模板
2.2 手动显性调用模板
无法通过函数的参数,推导出所有的模板类型
显性调用模板函数的格式:
函数名<数据类型1,数据类型2......>(参数);
五、异常处理
1.throw
在可能发生异常的位置,提前抛出异常
throw 数据类型(值);
2.try。。。 catch。。。
throw用于抛出异常,try尝试接收异常并进行相应的处理
try{}中的存放可能发生异常的代码,接收到throw抛出的异常,但是只能接收一次,所以建议try中只存放一条语句
catch对try获取到的异常进行处理,可以对数据类型处理,也可以对数据的值处理
作业
1.使用模板类,实现顺序栈
#include <iostream>
using namespace std;
template<typename T>
class Seq{
public:
T *data; //数据
int top; //栈顶指针
int maxsize;//栈容量
//分配空间
Seq(int maxsize);
//释放空间
~Seq();
//入栈
void push(T data);
//出栈
void pop();
//展示栈中元素
void show();
//判满
bool full();
//判空
bool empty();
};
template<typename T>
//分配空间
Seq<T>::Seq(int maxsize):maxsize(maxsize),top(-1){
data=new T[maxsize];
}
template<typename T>
//释放空间
Seq<T>::~Seq(){}
template<typename T>
//入栈
void Seq<T>::push(T value){
if(!full())
data[++top]=value;
}
template<typename T>
//出栈
void Seq<T>::pop(){
if(!empty()){
T temp=data[top--];
cout<<"出栈元素为"<<temp<<endl;
}
}
template<typename T>
//展示栈中元素
void Seq<T>::show(){
cout<<"栈中元素为: ";
for(int i=0;i<=top;i++){
cout<<data[i]<<" ";
}
}
template<typename T>
//判满
bool Seq<T>::full(){
return top==maxsize;
}
template<typename T>
//判控
bool Seq<T>::empty(){
return top==-1;
}
int main()
{
Seq <int>s(10);
s.push(10);
s.push(20);
s.push(30);
s.pop();
s.show();
}
2.写一个char类型的字符数组,对该数组访问越界时抛出异常,并做处理。
#include <iostream>
#include <cstring>
using namespace std;
int fun(int a,int len){
if(a>len-1){
throw int();
}
cout<<"下标为"<<a<<endl;
}
int main()
{
int a;
cout<<"请输入下标位置"<<endl;
cin>>a;
char arr[32]="hello";
int len=strlen(arr);
try{
fun(a,len);
}catch(int){
cout<<"越界访问"<<endl;
}
return 0;
}