C++類指針初始化
阿新 • • 發佈:2018-02-18
類成員函數 類指針 沒有 int mar 但是 編譯器 public 解釋
上面的代碼會打印“A”。
C++ 類指針定義的時候沒有初始化的時候,居然可以安全的調用類內部的成員函數而不出錯。
在網上查了一下:
初始化為NULL的類指針可以安全的調用不涉及類成員變量的類成員函數而不出錯,但是如果類成員函數中調用了類成員變量則會出錯,既然賦值為NULL的情況都可以使用,那麽自然不初始化的類指針同樣滿足這類情況。
假設現在有一個簡單的類定義如下:
class Test
{
public:
void func(){cout << "hahaha" << endl;}
int get(){return a+b;}
Test():a(1),b(2){}
public:
int a,b;
};
而之後編譯器會自動將這個類轉換成:
class Test
{
int a,b;
};
void _test_func(Test * this);
int _test_get(Test* this);
........
類中的函數被編譯器靜態編譯了,所有非虛函數(虛函數呢?別急,待會會解釋到)都可以調用,因為函數地址編譯期間已經確定。我們知道,類中的成員函數都是通過this指針調用成員變量的,編譯器會將this指針作為默認參數傳給類成員函數的,如myclass.function(int a,int b) --> function(&myclass,int a,int b)
添加main函數如下:
int main()
{
Test *p=NULL;
p->func();//正確,沒有調用成員變量,沒有使用空的this指針
p->get();//錯誤,this指針為空,通過this指針調用變量所以出錯
return 0;
}
運行結果如上,沒有調用成員變量的func()函數正確執行,調用了成員變量的get()函數錯誤。兩者其實都傳入了空的this指針,前者沒出錯僅僅是因為沒有調用this指針,而後者調用了。(此時p-func()和p->get()等同於func(NULL),get(NULL)......)是對象指針為NULL,而調用成員函數的時候,函數地址是編譯期間確定的,成員函數不通過對象指針(也即當前的p指針)去調用,對象指針僅僅作為參數傳入函數然後去調用成員變量。
好現在問題來了,如果是虛函數呢,因為虛函數要通過this指針計算vptr,然後找到vtable,然後dispatch。因為this指針為空,所以在找vtable時候就會coredump了。總之這類情況下,一切調用了this指針的函數都會出錯,而完全不調用this指針的成員函數則沒問題。
總結:任何時候定義指針的時候一定要初始化,這是良好的習慣,這個問題最初是由於當時寫程序疏忽造成的,然而錯有錯著居然編譯通過,所以當時一直沒發現這個手誤,現在追本溯源也算是對c++的內部機制有了更深的了解,不過也提示自己不能有僥幸心理,一定要養成良好的編程習慣,不管對於自己還是對於以後合作的夥伴都是一件好事。
class Test
{
public:
void func(){cout << "hahaha" << endl;}
int get(){return a+b;}
Test():a(1),b(2){}
public:
int a,b;
};
而之後編譯器會自動將這個類轉換成:
class Test
{
int a,b;
};
void _test_func(Test * this);
int _test_get(Test* this);
........
類中的函數被編譯器靜態編譯了,所有非虛函數(虛函數呢?別急,待會會解釋到)都可以調用,因為函數地址編譯期間已經確定。我們知道,類中的成員函數都是通過this指針調用成員變量的,編譯器會將this指針作為默認參數傳給類成員函數的,如myclass.function(int a,int b) --> function(&myclass,int a,int b)
添加main函數如下:
int main()
{
Test *p=NULL;
p->func();//正確,沒有調用成員變量,沒有使用空的this指針
p->get();//錯誤,this指針為空,通過this指針調用變量所以出錯
return 0;
}
運行結果如上,沒有調用成員變量的func()函數正確執行,調用了成員變量的get()函數錯誤。兩者其實都傳入了空的this指針,前者沒出錯僅僅是因為沒有調用this指針,而後者調用了。(此時p-func()和p->get()等同於func(NULL),get(NULL)......)是對象指針為NULL,而調用成員函數的時候,函數地址是編譯期間確定的,成員函數不通過對象指針(也即當前的p指針)去調用,對象指針僅僅作為參數傳入函數然後去調用成員變量。
好現在問題來了,如果是虛函數呢,因為虛函數要通過this指針計算vptr,然後找到vtable,然後dispatch。因為this指針為空,所以在找vtable時候就會coredump了。總之這類情況下,一切調用了this指針的函數都會出錯,而完全不調用this指針的成員函數則沒問題。
總結:任何時候定義指針的時候一定要初始化,這是良好的習慣,這個問題最初是由於當時寫程序疏忽造成的,然而錯有錯著居然編譯通過,所以當時一直沒發現這個手誤,現在追本溯源也算是對c++的內部機制有了更深的了解,不過也提示自己不能有僥幸心理,一定要養成良好的編程習慣,不管對於自己還是對於以後合作的夥伴都是一件好事。
C++類指針初始化