这里有详细的解释
https://www.codeproject.com/Articles/14879/Pure-Virtual-Function-Call
当一个对象包含一个纯虚函数(一个未实现的函数)时,这个对象根本不能被构造,因此纯虚函数不能被称为全部。试试下面的代码:
class Parent {
public:
Parent() {
}
~Parent() {
ClearALL();
}
void ClearALL() {
ThePure();
}
virtual bool ThePure() = 0 ;
}
;
void main() {
Parent P;
/*error C2259: 'Parent' : cannot instantiate abstract class due to following members: Parent::ThePure(void)*/
}
等等……可以做到…
那么,一个纯虚函数是如何被调用的呢?为了生产它,让我们继续工作,从父类继承一个新的类。我们叫它孩子吧。因此,我们有以下代码:
class Parent {
public:
Parent() {
}
~Parent() {
ClearALL();
}
void ClearALL() {
ThePure();
}
virtual bool ThePure() = 0 ;
}
;
class Child : public Parent {
public:
Child() {
}
~Child() {
}
/* The implementation of the pure virtual function */
virtual bool ThePure() {
return true;
}
}
;
void main() {
Child c;
}
现在,我们对我们所做的多态性很满意,然后运行我们的程序,然后得到“纯虚拟函数调用”的震撼。
为了分析这一点,让我们假设一个纯虚函数。调用该函数thepure()但版本,没有实现我们应该从父类别对象并调用函数把它像:
Parent P;
P.ThePure(); //Compilation Error!
这当然是不可能的,但等等,这是可能的。怎么用????
我们都知道从面向对象的概念来看,当一个对象被破坏时,它被称为析构函数,然后是它的父类的析构函数等等,直到我们到达该家族的第一个父节点,然后销毁过程就完成了。因此,如果您检查了上面的代码,就会看到在父析构函数中,我们调用一个函数,函数反过来调用一个纯虚函数。在父代码中写这是合法的,因为在运行时不可能有它的实例。当然,代码将运行在类型子对象中(因为父代不能完全按照我们所说的构造)。但是此时(父析构函数内部)被调用并完成了子析构函数,因此,我们现在没有一个类型子对象,但是当前对象(只被破坏)是类型父类,所以析构函数中的所有调用都是对这个对象中函数的调用。因此,可以得到纯虚函数。
编译器有时会有帮助
现在,你要问上面的代码的问题是,为什么我不叫纯虚函数直接与其说clearall()反过来调用它的析构函数。答案是幸福的消息。编译器很聪明,可以检测出这样的错误(为什么?)并发出链接错误。但是如果像这样间接调用它,编译器将对调用链中的函数视而不见,获得纯虚函数。
我在vc++ 6和vc++ 2003下编译了这个代码,结果也一样。
结论
因此,为了避免这个错误,您不应该调用析构函数中的函数,调用函数在这个对象中没有实现的功能。