靜態成員經典應用-單例模式(C++)
單例模式:設計模式的一種, 保證某個類永遠只創建一個對象.
1.構造函數\析構函數私有化, 拷貝構造函數私有化, 賦值運算符重載函數私有化.
2.定義一個私有的static成員變量指向唯一的那個單例對象
3.提供一個公共的訪問單例對象的接口.
#include <iostream>
using namespace std;
class Rocket {
private:
static Rocket *ms_rocket;
Rocket() {}
Rocket(const Rocket &rocket) {}
~Rocket() {}
void operator=(const Rocket &rocket) {}
public:
static Rocket *sharedRocket() {
// 這裏要考慮多線程安全
if (ms_rocket == NULL) {
ms_rocket = new Rocket();
}
return ms_rocket;
}
static void deleteRocket() {
// 這裏要考慮多線程安全
if (ms_rocket != NULL) {
delete ms_rocket;
ms_rocket = NULL;
// 防止野指針
}
}
void run() {
cout << "run()" << endl;
}
};
Rocket *Rocket::ms_rocket = NULL;
int main()
{
Rocket *p = Rocket::sharedRocket();
p->run();
p->deleteRocket();
return 0;
}
(1)爲什麼要用指針?
1.在C++開發中, 對象能放堆空間, 儘量放堆空間.
2.對於單例對象, 要考慮內存的靈活使用, 因爲牽扯到內存的分配和銷燬, 所以用堆空間更靈活.
(2)賦值運算符重載函數爲什麼要私有化?
因爲兩個一樣的對象做賦值操作沒有意義.
(3)拷貝構造函數爲什麼要私有化?
因爲如果不寫拷貝構造函數, 還可以通過調用默認的拷貝構造函數去構建對象.如:
Rocket *p1 = Rocket::sharedRocket();
Rocket *p2 = new Rocket(*p1)
多態4-虛表的彙編分析
調用speak()
// 調用speak
Animal *cat = new Cat();
cat->speak();
// ebp-8 是指針變量cat的地址
mov eax, dword ptr [ebp-8]
// 根據指針變量的地址, 找到指針變量的存儲空間, 取出存儲空間裏面的東西, 也就是Cat對象的地址給eax
// 所以eax是Cat對象的地址
mov edx, dword ptr [eax]
// 根據Cat對象的地址值, 找到Cat對象的存儲空間, 取出4個字節出來賦值給edx
// 取出Cat對象最前面的4個字節(虛表的地址)給edx
mov eax, dword ptr [edx]
// 根據edx的地址值, 找到edx的存儲空間, 取出虛表的前4個字節(Cat::speak的函數地址)賦值給eax
call eax
// call Cat::speak 調用函數
調用run()
// 調用run
Animal *cat = new Cat();
cat->run();
// ebp-8 是指針變量cat的地址
mov eax, dword ptr [ebp-8]
// 所以eax是Cat對象的地址
mov edx, dword ptr [eax]
// 根據Cat對象的地址值, 找到Cat對象的存儲空間, 取出4個字節出來賦值給edx
// 取出Cat對象最前面的4個字節(虛表的地址)給edx
mov eax, dword ptr [edx+4]
// 根據edx+4之後的地址值, 從這個地址值開始找到它的存儲空間, 取出4個字節(Cat::run的函數地址)賦值給eax
// 跳過虛表的最前面4個字節, 在取出4個字節(Cat::run的函數地址)賦值給eax
call eax
// call Cat::run 調用函數