如题,看到一篇文章,说只要非静态成员函数中没有使用非静态成员变量,就可以通过类名和域运算符来直接调用非静态成员函数,而不需要实例来调用,是这样吗?编译器为vs2013
认证高级PHP讲师
類別名稱可以存取非靜態成員才怪了,那我怎麼區分存取的是哪個物件的非靜態?靜態可以理解為,所有用該類別創建的物件都共享的變數。
只要非靜態成員函數中沒有使用非靜態成員變數
這句話的意思是non-static member function裡面沒有對this指針的調用,沒有調用this的non-static member function其實和static member差不了太多的。
你可以先把一個nullptr轉換成對應的class類型,再呼叫這個non-static memrber function,如下:
class A { public: void printHello() { cout << "hello" << endl; } }; void test() { A *p = nullptr; p.printHello(); }
正規的C++語言標準目前(截止到C++14)應該還不支援這種呼叫方法。 目前微軟似乎在它的VC++中推行一種叫做C++/CLI的標準,有可能會支援這種調用,如果一定要用這種調用方法的話,還應該用VS2013嘗試編譯運行一下。
實際上,C++語言中類別的靜態成員函數本身應該是所有這一類物件的集體所具有的行為,就是說,不是某一個物件能夠具有或說實現的;而非靜態成員函數應該是某一個物件自己的動作行為,跟本類其他物件乃至整個類別關係不大,是物件依靠自己的資料以及函數參數就可以完成的行為。 根據以上的討論,我們可以看出,很難存在一種需求,使得一個成員函數不需要引用本對象的非靜態成員,同時又必須是一個對象自己的行為(即聲明為非靜態成員函數)。如果真的存在不引用非靜態成員的成員函數,那還是直接宣告為靜態成員函數為好,這樣就可以萬無一失地通過編譯,也避免了移植性問題。
說句題外話,非靜態成員函數總會有一個隱含的參數,就是this指標。透過反組譯分析也可以發現,非靜態成員函數的呼叫屬於特殊的thiscall,就是說總是會傳入一個this指標。而靜態成員函數和類別外的函數一樣,經過編譯後都是普通的調用,不會得到this指針,因此也不可能存取非靜態成員(因為非靜態成員的引用總是透過this指針完成的)。因此一個函數能否透過類別名稱調用,主要還是要看它是否需要編譯器傳入this指標(要看編譯後的程式碼,原始碼層級上的調用是看不到傳入的this指標的)。
如果真的希望在沒有實例的前提下,調用一個非靜態成員函數,可以使用下面的方法(前提是必須符合您提出的那個條件,即不訪問任何非靜態成員,如果它訪問了非靜態成員,則可能導致記憶體讀寫異常):
// 假设要引用的类类型为 TargetType, 成员函数为 void TargetType::TargetFunc(); // C++11 版: static_cast<TargetType *>(nullptr)->TargetFunc(); // C++98/03 版: reinterpret_cast<TargetType *>(0)->TargetFunc(); // 如果使用 C 风格的类型转换操作符: ((TargetType *) 0)->TargetFunc();
類別名稱可以存取非靜態成員才怪了,那我怎麼區分存取的是哪個物件的非靜態?靜態可以理解為,所有用該類別創建的物件都共享的變數。
這句話的意思是non-static member function裡面沒有對this指針的調用,沒有調用this的non-static member function其實和static member差不了太多的。
你可以先把一個nullptr轉換成對應的class類型,再呼叫這個non-static memrber function,如下:
正規的C++語言標準目前(截止到C++14)應該還不支援這種呼叫方法。
目前微軟似乎在它的VC++中推行一種叫做C++/CLI的標準,有可能會支援這種調用,如果一定要用這種調用方法的話,還應該用VS2013嘗試編譯運行一下。
實際上,C++語言中類別的靜態成員函數本身應該是所有這一類物件的集體所具有的行為,就是說,不是某一個物件能夠具有或說實現的;而非靜態成員函數應該是某一個物件自己的動作行為,跟本類其他物件乃至整個類別關係不大,是物件依靠自己的資料以及函數參數就可以完成的行為。
根據以上的討論,我們可以看出,很難存在一種需求,使得一個成員函數不需要引用本對象的非靜態成員,同時又必須是一個對象自己的行為(即聲明為非靜態成員函數)。如果真的存在不引用非靜態成員的成員函數,那還是直接宣告為靜態成員函數為好,這樣就可以萬無一失地通過編譯,也避免了移植性問題。
說句題外話,非靜態成員函數總會有一個隱含的參數,就是this指標。透過反組譯分析也可以發現,非靜態成員函數的呼叫屬於特殊的thiscall,就是說總是會傳入一個this指標。而靜態成員函數和類別外的函數一樣,經過編譯後都是普通的調用,不會得到this指針,因此也不可能存取非靜態成員(因為非靜態成員的引用總是透過this指針完成的)。因此一個函數能否透過類別名稱調用,主要還是要看它是否需要編譯器傳入this指標(要看編譯後的程式碼,原始碼層級上的調用是看不到傳入的this指標的)。
如果真的希望在沒有實例的前提下,調用一個非靜態成員函數,可以使用下面的方法(前提是必須符合您提出的那個條件,即不訪問任何非靜態成員,如果它訪問了非靜態成員,則可能導致記憶體讀寫異常):