1.基本概念
非靜態成員函數都會默認傳遞this指針(靜態成員函數屬于類本身,不屬于某個實例對象),方便訪問對象對類成員變量和 成員函數。
2.基本使用
編譯器實際處理類成員函數,this是第一個隱藏的參數,類型為指向當前對象的指針
void func(); // 表面形式
void func(MyClass* this); // 實際內部形式
編輯代碼
class MyClass {
public:int a;void show() {std::cout << a << std::endl; // 相當于 std::cout << this->a;}
};
編譯器處理
void show(MyClass* this) {std::cout << this->a << std::endl;
}
2.1區分參數和類成員變量
類成員函數中變量/函數查找順序:①當前作用域->②函數參數->③類成員變量/函數(通過this指針查找)->④父類成員->⑤編譯器報錯。
通過this指針可以區分類成員變量還是傳入參數
#include <iostream>using namespace std;class Persion {
public:void SetAge(int age) {this->age = age; // this指針指向調用成員函數的對象本身}void SetHeight(double height) {height = height; // 優先使用局部變量height,未使用this指針}void ShowAge() {cout << "Age: " << age << endl; // 使用this指針訪問成員變量} void ShowHeight() {cout << "Height: " << height << endl; // 使用this指針訪問成員變量}int age = 0;double height = 0;
};int main() {Persion p;p.SetAge(25);p.SetHeight(175.5);p.ShowAge(); // 輸出: Age: 25p.ShowHeight(); // 輸出: Height: 0return 0;
}
ShowAge方法中,先查找函數作用域沒有age變量,通過隱藏this指針查找到類成員變量age
2.2鏈式調用
通過返回this可以實現鏈式調用
#include <iostream>using namespace std;class Persion {
public://需要使用返回Person的引用的方式,才能實現鏈式調用,否則會重新創建一個對象Persion& SetAge(int age) {this->age = age; // this指針指向調用成員函數的對象本身return *this; // 返回對象本身的引用}Persion& SetHeight(double height) {this->height = height; // 優先使用局部變量height,未使用this指針return *this; // 返回對象本身的引用}void ShowAge() {cout << "Age: " << age << endl; // 使用this指針訪問成員變量} void ShowHeight() {cout << "Height: " << height << endl; // 使用this指針訪問成員變量}int age = 0;double height = 0;
};int main() {Persion p;p.SetAge(25).SetHeight(175.5);p.ShowAge(); // 輸出: Age: 25p.ShowHeight(); // 輸出: Height: 175.5return 0;
}
3.問題
1.非靜態類成員函數中使用的this是類成員變量還是編譯器隱式傳遞的this參數
this指針不是一個類成員變量,類成員函數中使用的this指針是編譯器隱式傳遞的this參數。(這就是為什么靜態成員函數里不能使用類成員變量和類成員函數,因為靜態成員函數沒有this指針參數,在函數內部就無法通過this指針找到對應的實例對象的成員變量以及成員函數)
#include <iostream>using namespace std;class Persion {//this指針是隱含在所有非靜態成員函數中的一個指針,指向調用該成員函數的對象,編譯器會自動傳遞this指針//this指針不是類成員變量
public://非靜態成員函數編譯器會自動傳遞this指針void setAge(int a) {this->age = a;//通過this指針訪問成員變量}//靜態成員函數編譯器不會自動傳遞this指針static void getAge() {cout << "age is " << this->age << endl;//報錯,靜態成員函數沒有this指針}int age;
};int main() {Persion p;return 0;
}
2.什么情況自動獲取this指針并傳遞給類成員函數,什么時候需要手動傳遞?
編譯器自動傳遞this指針:在非靜態成員函數內部調用類成員函數和類成員變量時(非靜態成員函數本身有隱藏this指針參數)或則通過對象直接調用非靜態成員函數時(編譯器會根據對象自動生成指向該對象的指針),this指針會被編譯器自動傳遞。
需要手動傳遞this指針:當將靜態成員函數“脫離對象上下文”傳遞(如給線程或lambda表達式,必須手動指定this。
#include <iostream>
#include <thread>using namespace std;class Persion {
public://需要使用返回Person的引用的方式,才能實現鏈式調用,否則會重新創建一個對象Persion& SetAge(int age) {this->age = age; // this指針指向調用成員函數的對象本身return *this; // 返回對象本身的引用}Persion& SetHeight(double height) {this->height = height; // 優先使用局部變量height,未使用this指針return *this; // 返回對象本身的引用}void ShowAge() {cout << "Age: " << age << endl; // 使用this指針訪問成員變量} void ShowHeight() {cout << "Height: " << height << endl; // 使用this指針訪問成員變量}void testThisPoint() {std::thread t1(&Persion::ShowAge, this); // 傳遞this指針,必須顯示傳遞類成員函數ShowAge第一個參數thisstd::thread t2([this]() { ShowHeight(); }); // 使用lambda表達式捕獲this指針,表示式作用域內找不到ShowHeight方法,再通過this指針訪問t1.join();t2.join();std::cout << t1.joinable() << std::endl;std::cout << t2.joinable() << std::endl;}int age = 0;double height = 0;
};int main() {Persion p;p.SetAge(25).SetHeight(175.5);p.testThisPoint();return 0;
}
3.成員函數如何區分使用變量是類成員變量還是未定義變量或則傳入參數變量?this指針工作原理
層層查找,和普通變量作用域一樣,從內到外層層查找
①當前作用域->②函數參數->③類成員變量/函數(通過this指針查找)->④父類成員->⑤編譯器報錯。
4.總結
1.this指針不是一個類成員變量,類成員函數中使用的this指針是編譯器隱式傳遞的this參數。