同事在debug中遇到了這樣一個問題:
1 class basic 2 { 3 public: 4 basic() {cout << "basic ctor " << endl;} 5 virtual ~basic() {cout << " basic dtor" << endl;} 6 virtual void foo() { cout << "basic foo" << endl;}
private:
char data[4]; 7 }; 8 9 10 class deride: public basic11 {12 public:13 deride() { cout << "deride ctor " << endl;}14 virtual ~deride() {cout << "deride dtor" << endl;}15 virtual void foo() { cout <<"deride foo" << endl;}
private:
char data[6];16 };17 18 19 int main()20 {21 22 basic * pb = new deride[20];23 24 pb[1].foo();//正確嗎?25 26 delete[] pb;//正確嗎?27 28 return 0;29 }
上述兩個調用都是有問題,原因如下:
pb[1].foo() 這種調用包含以下幾方面要注意的地方:
1)pb[1] = *(pb + sizeof(basic));
而pb事實上是指向deride類型的記憶體,如果sizeof(basic) != sizeof(deride),那pb[1]這種訪問方式並不能正確的定位deride[10]中的正確位置。
2)pb[1].foo(),foo()是virtual,這裡進行函數調用需要訪問虛函數表。
3)一般來說,vptr預設放在一個固定的位置,如類的最開頭,因此,只有正確擷取到當前對象的指標,才能正確擷取vptr。
基於以上三點分析,可以得到如下結論:
1)pb[1].foo()這種調用上述的代碼中是不正確的。
2)delete [] pb 也同樣不正確。