這篇的標題是呼叫純虛擬函式
一個沒有實作的純虛擬函式是有可能被呼叫起來的
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時 就會呼叫純虛擬函式了