這篇的標題是呼叫純虛擬函式
一個沒有實作的純虛擬函式是有可能被呼叫起來的
class A { public: virtual void f(void) = 0; }; class B : public A { virtual void f(void) {} };在系統開發中 這是一個很常出現的程式片斷
在多型體系中
A* a = new B;
a->f();
因為vtable的存在 程式會為f找尋合適的function pointer並呼叫
這例子中從vtable中會找到class B中的f()
這並沒有甚麼問題
那麼如果vtable中沒有class B的資訊時會怎麼樣 那就會找到class A的f()
就會呼叫純虛擬函式了
這會發生嗎?
會的
class A; class A { public: virtual ~A() { m_pA->Close(); } virtual void Close(void) = 0; A* m_pA; }; class B : public A { virtual void Close(void) {} };像這樣的程式
一般人會想說把所有的CloseXXX, DeleteXXX, DestoryXXX寫在解構子
解構子被呼叫的順序是從下而上
所以B的解構子先呼叫 把vtable清掉
A的解構子再呼叫 這時vtable中只有class A 所以就呼叫一個純虛擬函式了
當然 Effective C++裡提到 不應該在解構子呼叫虛擬函式 會有類似的問題出現
而在多執行緒中 也可能發生
class B : public A { virtual void f(void) {} void ThreadProc() { while(1) f(); } }; void main() { A* a = new B(); while(1) { if (...) a->Create(); if (exception == true) break; } delete a; }我們把class B改為一個thread 它會不斷的呼叫f()
當一個執行緒因為例外發生或其他原因 使物件的解構子被呼叫
呼叫到一半的時候 另一個執行緒呼叫該物件的虛擬函式
剛好解構到vtable只剩下Base class時 就會呼叫純虛擬函式了