C++11给出了一个关键字override:
只能修饰派生类中的虚函数
作用:让编译器帮助用户检测派生类中某个虚函数是否重写了基类的哪个虚函数。
主要作用就是防止在派生类中重写基类虚函数的时候手滑把函数名写错了,此时用户将派生类中的函数当作对基类的重写去使用,虽然此时编译可以通过,但是此时结果已经不正确了。
C++11:
final关键字
修饰类,表示该类不能被继承
修饰类中的函数,表示该函数不能作为虚函数被继承此类的子类重写。
重写和重定义区分:
3.抽象类:
在虚函数的后面写上 =0 ,则这个函数为纯虚函数。包含纯虚函数的类叫做抽象类(也叫接口类),抽象类
不能实例化出对象。派生类继承后也不能实例化出对象,只有重写纯虚函数,派生类才能实例化出对象。纯
虚函数规范了派生类必须重写,另外纯虚函数更体现出了接口继承。
#include<iostream>
using namespace std;
class WC
{
public:
void GoToManRoom()const
{
cout << "go to left" << endl;
}
void GoToWoManRoom()const
{
cout << "go to right" << endl;
}
};
class person //抽象类,将人类给成抽象类的原因就是人类,并不知道男女,也就不知道应该去那个厕所
{
public:
virtual void GoToWC(const WC& wc) = 0; //纯虚函数
string _name;
int _age;
};
class man : public person
{
public:
void GoToWC(const WC& wc)
{
wc.GoToManRoom(); //注意const成员只能调用const类型的成员函数
}
};
class woman : public person
{
public:
void GoToWC(const WC& wc)
{
wc.GoToWoManRoom();
}
};
void test()
{
WC wc;
woman c1;
c1.GoToWC(wc);
man c2;
c2.GoToWC(wc);
}
int main()
{
test();
return 0;
}
抽象类的作用就是规范后续要实现的接口
利用对象来观察Base类的对象内存模型:
确定虚函数表的存在:
根据对象模型的前四个字节找到虚函数表:
可以推出内存对象模型是
派生后再研究内存模型
上图派生类与基类的虚表内容相同是因为派生类并没有对基类的虚函数进行重写
下面这张图是在子类中对父类的虚函数进行了重写,所以虚表的内容也发生了改变
如果派生类重写了基类中的莫个虚函数,用派生类自己重写后的函数替换虚表中同偏移量的基类虚函数
1.同一个类,假如类中有虚函数,那么这个类所创建出来的多个对象在底层用的是同一张虚表
2.在基类有 虚函数的情况下,派生类和基类使用的不是同一张虚表,(为什么前提是要带有虚函数呢?因为积累不存在虚函数的话,那么也就不存在指向虚函数表的指针)
3.派生类永远也不会和基类使用同一张虚表,无论派生类是否对基类的虚函数进行重写
4.如果派生类对基类中的某个虚函数进行了重写,就用派生类自己的虚函数地址覆盖虚表中的相同偏移量位置的基类虚函数
5.如果在派生类中增加新的虚函数,就会在拷贝基类的虚函数表的后面,按照派生类中新增虚函数的顺序,将新增的虚函数放置在虚函数表的末尾
====================================================================================
插入 :
结果:4
结果:1