您的位置:首页 > 其它

Pure virtual function call error探讨

2008-07-13 09:56 507 查看
在实习的单位搞CxImage库时不知为什么在Debug时没有问题,但是Release版里竟然跳出个Purevirtualfunctioncallerror!啥东西呀,竟然遇上了,就探个究竟吧!
MSDN上的解释
http://forums.msdn.microsoft.com/zh-CN/clr/thread/bfa759a8-0cc0-4d65-8711-d2d0d6765687/

这时讲得很详细http://www.artima.com/cppsource/pure_virtual.html
看看Codeproject上的一个例子
http://www.codeproject.com/KB/cpp/PureVirtualFunctionCall.aspx

(1)出现Purevirtualfunctioncall的原因是:
thechilddestructoriscalledandfinished,so,wedon’thaveanobjectoftypechildnow,butthecurrentobject(whichisonlybeingdestructed)isoftypeParent,soallcallsinthedestructorarecallstofunctionsinthisobject.So,youcangetapurevirtualfunction.
继承类的对象析构被调用,而且完成了释放,那么现在这个对象就不存在了,但是当前的对象(正在释构的父类对象)却要调用其子类的虚函数实现(因为自身是纯虚函数),所以就会出现Purevirtualfunctioncallerror!

(2)由面向对象的概念知,对象的析构是子类先析构再到父类析构,所以如果在父类中要调用自身的虚纯数将会很危险了,而且在是运行时出现的。

以下是codeproject的例子

ClassParent

{

public:Parent(){}

~Parent(){

ClearALL();

}

voidClearALL()

{

ThePure();//调用自身的纯虚函数,包装一下是因为直接调用编译器会识别出这样调用是有问题的!

}

virtualboolThePure()=0;

};

classChild:publicParent

{

public:Child(){}

~Child(){}//TheimplementationofthepurevirtualfunctionvirtualboolThePure()

{

returntrue;

}

};

voidmain()

{

Childc;

}

当C析构时,虚函数表里的ThePure()已经注销,那么父类Parent里的ClearALL()里的ThePure()虚表指针就会指向一个空地址(成了danglingpointer了),所以在Parent里调用ClearALL()就会出错了

(3)如果上面的情况还算直观的话,看看下面的一种造成purevirtualfunctioncall的情况就更隐蔽了。

//不过我在VC6里没有问题

classBase

{

public:

virtualvoidfunction()=0;

};

classB:publicBase

{

public:

virtualvoidfunction()

{

cout<<"purefunctioncallinB"<<endl;

}

};

classA

{

public:

A(B*b):_b(b){}

~A()

{

_b->function();

}

B*_b;

};

Bb;

a(&b);

intmain()

{

return0;

}


这种情况在某些编译器下会出purevirtualfunctioncall错误。主要的原因是因为全局变量的释放顺序不确定,全局变量A依赖全局变量B。如果编译器决定让B先释放,A后释放。那么,当A析构时,_b是一个danglingpointer。此时如果b对象的内存系统没有释放的话,那么b的vptr表指向的是Base的vptr,而不是B的。此时,_b->function()就指向了purevirtualfunction了。详细情况可以到看看

/article/7054126.html

(5)论坛上关于出现purevirtualfunctioncall的情况总结:

1.基类构造器直接调用虚函数
2.基类析构器直接调用虚函数
3.基类构造器间接调用虚函数
4.基类析构器间接调用虚函数
5.Callingavirtualfunctionviaadanglingpointer.
(4)为了在遇到purevirtualfunctioncall时不致于程序蹦掉,可以实现在一基类的纯虚函数,但要记住找出原因后要删掉实现的代码


                                            
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: