C++建構函式中呼叫虛擬函式
阿新 • • 發佈:2018-12-30
談談關於建構函式中呼叫虛擬函式的情況,僅討論單繼承,不考慮虛擬繼承和多重繼承。
測試平臺:VS2013 + Win7X64
一個例子:
輸出: Base::Func Deri::Func 首先討論下物件d的構造情況。 1 先構造基類部分,呼叫基類Base的建構函式,這個時候,派生類部分還沒有產生,這時候虛表應該是繫結基類的,自然呼叫的是Base::Func() 2 再構造派生類部分,這個時候,虛表發生變化,繫結在派生類上,呼叫Deri::Func() 雖然,在派生類中有過載Func這個函式,但是,在構造基類部分的時候,派生類的成員資料還沒有初始化,如果是呼叫派生類中的Func,會造成錯誤,記憶體越界甚至崩潰。 在函式中,可以通過列印虛表地址: -- Base::Func() int* vtl = (int*)*((int*)this); std::cout << "Base: " << this << " VTable: " << vtl << std::endl; -- Deri::Func() int* vtl = (int*)*((int*)this); std::cout << "Deri: " << this << " VTable: " << vtl << std::endl; 輸出: Base: 0028F980 VTable: 003FDC78
Deri: 0028F980 VTable: 003FDC98 發現,虛表的地址是不斷變化的。
#include <stdlib.h> #include <stdio.h> class Base { private: int __data; public: Base() { this->Func(); } public: virtual void Func() { printf("Base::Func"); } }; class Deri : public Base { public: Deri() { this->Func(); } public: virtual void Func() { printf("Deri::Func\n"); } }; int main(int argc, char** argv) { Deri d; getchar(); return 0; }
輸出: Base::Func Deri::Func 首先討論下物件d的構造情況。 1 先構造基類部分,呼叫基類Base的建構函式,這個時候,派生類部分還沒有產生,這時候虛表應該是繫結基類的,自然呼叫的是Base::Func() 2 再構造派生類部分,這個時候,虛表發生變化,繫結在派生類上,呼叫Deri::Func() 雖然,在派生類中有過載Func這個函式,但是,在構造基類部分的時候,派生類的成員資料還沒有初始化,如果是呼叫派生類中的Func,會造成錯誤,記憶體越界甚至崩潰。 在函式中,可以通過列印虛表地址: -- Base::Func() int* vtl = (int*)*((int*)this); std::cout << "Base: " << this << " VTable: " << vtl << std::endl; -- Deri::Func() int* vtl = (int*)*((int*)this); std::cout << "Deri: " << this << " VTable: " << vtl << std::endl; 輸出: Base: 0028F980 VTable: 003FDC78
Deri: 0028F980 VTable: 003FDC98 發現,虛表的地址是不斷變化的。