C++ 笔记(18)— 类和对象(this 指针、指向类的指针、类静态成员变量和函数)
1. this 指針
在 C++ 中,每一個對象都能通過 this 指針來訪問自己的地址。 this 指針是所有成員函數的隱含參數。因此,在成員函數內部,它可以用來指向調用對象。
友元函數沒有 this 指針,因為友元不是類的成員。只有成員函數才有 this 指針。
在類中,關鍵字 this 包含當前對象的地址,換句話說,其值為 &object 。當您在類成員方法中調用其他成員方法時,編譯器將隱式地傳遞 this 指針—函數調用中不可見的參數:
class Human
{private:void Talk(string msg){cout << msg << endl;}public:void IntroduceSelf(){Talk("hello world"); // Talk(this, "hello world")}
}
方法 IntroduceSelf() 使用私有成員 Talk() 在屏幕上顯示一句話。實際上,編譯器將在調用 Talk 時嵌入 this 指針,即 Talk(this, "hello world") 。
從編程的角度看, this 的用途不多,且大多數情況下都是可選的。見下:
void SetAge(int humansAge)
{this->age = humansAge; // same as age = humansAge
}
調用靜態方法時,不會隱式地傳遞 this 指針,因為靜態函數不與類實例相關聯,而由所有實例共享。要在靜態函數中使用實例變量,應顯式地聲明一個形參,并將實參設置為 this 指針。
因為 this 的目的總是指向“這個”對象,所以 this 是一個常量指針,我們不允許改變 this 中保存的地址。
2. 指向類的指針
一個指向 C++ 類的指針與指向結構的指針類似,訪問指向類的指針的成員,需要使用成員訪問運算符 -> ,就像訪問指向結構的指針一樣。與所有的指針一樣,您必須在使用指針之前,對指針進行初始化。
#include <iostream>
#include <string>
using namespace std;class Box
{public:// 構造函數聲明Box(double, double, double);double Volume();private:double length; // Length of a boxdouble breadth; // Breadth of a boxdouble height; // Height of a box
};Box::Box(double l=2.0, double b=2.0, double h=2.0)
{ cout <<"Constructor called." << endl;length = l;breadth = b;height = h;
}double Box::Volume()
{return length * breadth * height;
}int main(void)
{Box Box1(3.3, 1.2, 1.5); // Declare box1Box Box2(8.5, 6.0, 2.0); // Declare box2Box *ptrBox; // Declare pointer to a class.// 保存第一個對象的地址ptrBox = &Box1;// 現在嘗試使用成員訪問運算符來訪問成員cout << "Volume of Box1: " << ptrBox->Volume() << endl;// 保存第二個對象的地址ptrBox = &Box2;// 現在嘗試使用成員訪問運算符來訪問成員cout << "Volume of Box2: " << ptrBox->Volume() << endl;return 0;
}
3. 類靜態成員
可以使用 static 關鍵字來把類成員定義為靜態的。當我們聲明類的成員為靜態時,這意味著無論創建多少個類的對象,靜態成員都只有一個副本。
靜態成員在類的所有對象中是共享的。如果不存在其他的初始化語句,在創建第一個對象時,所有的靜態數據都會被初始化為零。
我們不能把靜態成員的初始化放置在類的定義中,但是可以在類的外部通過使用范圍解析運算符 :: 來重新聲明靜態變量從而對它進行初始化,如下面的實例所示。
3.1 靜態成員變量
靜態成員數據也可以分為共有的(Public)和私有的(Private),靜態成員數據的聲明方法為:
static data_type data_name;
由于靜態成員數據不是僅僅屬于某一個具體對象的,所以它不能再構造函數中被初始化。否則豈不是每創建一個對象,靜態成員數據都要被初始化一次?
如果類的頭文件會被直接或間接地重復包含,則靜態成員數據也會被重復初始化。為了避免這個問題,我們可以將類的聲明和定義分離。
如果類的頭文件絕對不會被重復包含,那么把靜態成員數據的初始化放在類的頭文件中也是勉強可以接受的。
靜態成員數據的初始化語句為:
數據類型 類名::靜態成員數據=初始值;
靜態成員數據是某一個類所具有的屬性,而不是某一個對象的屬性,所以它的存在并不依賴于對象。
示例代碼:
#include <iostream>
#include <string>
using namespace std;class Box
{public:Box(double, double, double); // 構造函數聲明double Volume();static int objectCount;private:double length; // Length of a boxdouble breadth; // Breadth of a boxdouble height; // Height of a box
};// 初始化類 Box 的靜態成員
int Box::objectCount = 0;Box::Box(double l=2.0, double b=2.0, double h=2.0)
{ cout <<"Constructor called." << endl;length = l;breadth = b;height = h;objectCount++; // 每次創建對象時增加 1
}double Box::Volume()
{return length * breadth * height;
}int main(void)
{Box Box1(3.3, 1.2, 1.5); // 聲明 box1Box Box2(8.5, 6.0, 2.0); // 聲明 box2// 輸出對象的總數// Total objects: 2cout << "Total objects: " << Box::objectCount << endl;return 0;
}
3.2 靜態成員函數
既然成員數據可以屬于某一個類而不屬于某一個具體的對象,那么成員函數也可以這樣。在 C++ 中靜態成員函數也是屬于某一個類而不屬于某一個具體的對象的。
靜態成員函數的聲明方法為:
static 返回值類型 函數名(參數表);
不過在定義靜態成員函數時,卻不能出現 static 。
如果把函數成員聲明為靜態的,就可以把函數與類的任何特定對象獨立開來。靜態成員函數即使在類對象不存在的情況下也能被調用,靜態函數只要使用類名加范圍解析運算符 :: 就可以訪問。
由于靜態成員函數是屬于類的,不是屬于某一個具體的對象,所以它分不清楚到底是哪個對象的非靜態成員數據,故而不能訪問非靜態成員數據。
所以靜態成員函數只能訪問靜態成員變量數據、其他靜態成員函數和類外部的其他函數。
靜態成員函數有一個類范圍,他們不能訪問類的 this 指針。您可以使用靜態成員函數來判斷類的某些對象是否已被創建。
靜態成員函數與普通成員函數的區別:
- 靜態成員函數沒有
this指針,只能訪問靜態成員(包括靜態成員變量和靜態成員函數)。 - 普通成員函數有
this指針,可以訪問類中的任意成員;而靜態成員函數沒有this指針。
#include <iostream>
#include <string>
using namespace std;class Box
{public:Box(double, double, double); // 構造函數聲明double Volume();static int objectCount;static int getCount();private:double length; // Length of a boxdouble breadth; // Breadth of a boxdouble height; // Height of a box
};// 初始化類 Box 的靜態成員
int Box::objectCount = 0;// 在定義靜態成員函數時,卻不能出現 `static`
int Box::getCount()
{return objectCount;
}
Box::Box(double l=2.0, double b=2.0, double h=2.0)
{ cout <<"Constructor called." << endl;length = l;breadth = b;height = h;objectCount++; // 每次創建對象時增加 1
}double Box::Volume()
{return length * breadth * height;
}int main(void)
{// 在創建對象之前輸出對象的總數cout << "Inital Stage Count: " << Box::getCount() << endl;Box Box1(3.3, 1.2, 1.5); // 聲明 box1Box Box2(8.5, 6.0, 2.0); // 聲明 box2// 在創建對象之后輸出對象的總數cout << "Final Stage Count: " << Box2.getCount() << endl;return 0;
}
其中 Box2.getCount() 等價于 Box::getCount()。即 類型::靜態成員函數(參數列表) 等價于 對象名.靜態成員函數(參數列表),但更推薦前者,比較符合靜態成員函數定義。
輸出結果:
Inital Stage Count: 0
Constructor called.
Constructor called.
Final Stage Count: 2
類中特殊成員變量的初始化問題:
- 常量變量:必須通過構造函數參數列表進行初始化。
- 引用變量:必須通過構造函數參數列表進行初始化。
- 普通靜態變量:要在類外通過"::"初始化。
- 靜態整型常量:可以直接在定義的時候初始化。
- 靜態非整型常量:不能直接在定義的時候初始化。要在類外通過"::"初始化。
總結
以上是生活随笔為你收集整理的C++ 笔记(18)— 类和对象(this 指针、指向类的指针、类静态成员变量和函数)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 忏悔录作者是谁啊?
- 下一篇: C++ 笔记(19)— 标准模板库(ST