__cxa_pure_virtual报错(g++编译虚函数时)
g++编译os的memory'时不知道为什么报错。尝试了很多方法(也可能搜错了)
可以确定是纯虚函数出现了问题
复习一下虚函数的子类构造和析构的过程吧(一年过去了)
允许派生类调用父类的同名函数而实现不同的功能,也叫动态联编。
底层原理:虚函数表+虚函数表指针。每一个类都会对应一个虚函数表,一个存放虚函数地址的虚函数表,并创建虚函数指针(vptr)来指向表。
虚函数和纯虚函数的区别
纯虚函数和虚函数都可以在子类中被重写,他们的区别是:
1.纯虚函数只有定义,没有实现,而虚函数有定义,也有实现的代码。纯虚函数语法:virtual void print() = 0;
2.包含纯虚函数的类不能定义其对象,而包含虚函数的则可以。
所以,纯虚函数的作用就是在基类中定义这样的接口但是又不想去实现,所以就只好设置纯虚函数,因为只有这样才能编译通过。
纯虚函数(pure virtual) :C++中包含纯虚函数的类,被称为是“抽象类”。抽象类不能使用new出对象,只有实现了这个纯虚函数的子类才能new出对象。
虚函数指针的初始化过程
虚函数表的创建和虚函数指针的初始化都是在构造函数中进行的。当编译器发现基类当中有虚函数存在时,就会为每个含有虚函数的类创建一个虚函数表(vtable),该表是一个一维数组,存放的是虚函数的地址,子类中如果没有虚函数也会从基类中继承虚函数表,虚表创建之后还会创建一个虚函数指针来指向虚表,即(vptr)。
当基类的析构函数定义为虚函数的时候,子类可以利用自己的析构函数来调用基类的析构函数,从而达到整个类的完全析构。
第一步:构造最顶层的基类部分
a、让实例指向基类的虚函数表
b、构造基类实例成员变量
c、执行基类构造函数
第二步:构造派生部分(递归的)
a、让实例指向派生类的虚函数表
b、构造派生类实例成员变量
c、执行派生类构造函数
析构时则是按相反的顺序,就像这样:
第一步:析构派生部分(递归的)
a、(实例已经指向派生类的虚函数表)
b、执行派生类析构函数
c、析构派生类实例成员变量
第二步:析构基类部分(递归的)
a、让实例指向基类的虚函数表
b、执行基类析构函数
c、析构基类实例成员变量
根据上面的流程,构造函数和析构函数执行过程中,都有一段时间对象的虚函数指针指向基类虚函数表,如果在构造或者析构没有完成的时候调用了该对象的虚函数,则是调用了基类的纯虚函数。这种情况一般发生在多线程调用,构造或析构在一个线程,虚函数调用在另一个线程。
如果父类的函数不是纯虚函数,而是有实现的虚函数,则是调用父类的虚函数,不会crash
所以我怀疑是多线程的问题(但是我代码里没有多线程啊)https://gitee.com/saucerdish(代码可以看这里os)
我怀疑会不会是不能用纯虚类做全局变量呢,派生类做全局变量试试,发现也不行
让我们找找出错函数吧,没有emmm
看看.rodata段呢
停下来啊啊啊啊在这
后来我觉得真的只是没定义呢
试试extern一下这个东西吧
行吧,好像可以了