C++類與對象深入之靜態(tài)成員與友元及內(nèi)部類詳解
一:靜態(tài)成員
靜態(tài)成員就是在成員變量和成員函數(shù)前加上關鍵字static,稱為靜態(tài)成員。C++里面盡量用靜態(tài)成員變量代替全局變量。
1.1:靜態(tài)成員分類
1?靜態(tài)成員變量:
- 所有對象共享同一份數(shù)據(jù)
- 在編譯階段分配內(nèi)存
- 類內(nèi)聲明,類外初始化
靜態(tài)成員函數(shù)
- 所有對象共享同一個函數(shù)
- 靜態(tài)成員函數(shù)只能訪問靜態(tài)成員變量
1.2:靜態(tài)成員變量
class Person { public: static int m_A; //靜態(tài)成員變量 private: static int m_B; //靜態(tài)成員變量也是有訪問權限的 }; int Person::m_A = 10; int Person::m_B = 10; void test01() { //靜態(tài)成員變量兩種訪問方式 //1、通過對象 Person p1; p1.m_A = 100; cout << "p1.m_A = " << p1.m_A << endl; Person p2; p2.m_A = 200; cout << "p1.m_A = " << p1.m_A << endl; //共享同一份數(shù)據(jù) cout << "p2.m_A = " << p2.m_A << endl; //2、通過類名 cout << "m_A = " << Person::m_A << endl; //cout << "m_B = " << Person::m_B << endl; //私有權限訪問不到 } int main() { test01(); system("pause"); return 0; }
代碼解釋:上述代碼我們主要驗證了利用兩種方式來訪問靜態(tài)成員變量,以及靜態(tài)成員變量屬于整個類,屬于類的所有對象
1.3:靜態(tài)成員函數(shù)
class Person { public: static void func() { cout << "func調用" << endl; m_A = 100; //m_B = 100; //錯誤,不可以訪問非靜態(tài)成員變量 } static int m_A; //靜態(tài)成員變量 int m_B; // private: //靜態(tài)成員函數(shù)也是有訪問權限的 static void func2() { cout << "func2調用" << endl; } }; int Person::m_A = 10; void test01() { //靜態(tài)成員變量兩種訪問方式 //1、通過對象 Person p1; p1.func(); //2、通過類名 Person::func(); //Person::func2(); //私有權限訪問不到 } int main() { test01(); system("pause"); return 0; }
代碼解釋:上述代碼我們主要驗證了利用兩種方式來訪問靜態(tài)成員函數(shù),利用對象訪問和利用類名訪問,以及靜態(tài)成員函數(shù)只可以訪問靜態(tài)成員變量
??????:為什么不可以訪問非靜態(tài)成員?
??因為沒有this指針
1.4:總結特性
- 靜態(tài)成員為所有類對象所共享,不屬于某個具體的類實例
- 靜態(tài)成員變量必須在類外定義,定義時不加static關鍵字
- 類靜態(tài)成員類名::靜態(tài)成員或者對象.靜態(tài)成員來訪問
- 靜態(tài)成員函數(shù)沒有隱含的this指針,不可以訪問任何非靜態(tài)成員
- 靜態(tài)成員和類的普通成員也一樣,也有三種訪問權限,也可以有返回值。
1.5:試題示例
?實現(xiàn)一個類,計算程序中創(chuàng)建了多少個類對象
class A { public: A(){ ++_count1; } A(const A& aa){ ++_count2; } // 成員函數(shù)也可以是靜態(tài),static成員函數(shù)沒有this指針 static int GetCount1(){ return _count1; } static int GetCount2(){ return _count2; } //private: // 靜態(tài)成員變量屬于整個類,所以類的所有對象 static int _count1; static int _count2; // 聲明 }; // 定義 int A::_count1 = 0; int A::_count2 = 0; A Func(A a) { A copy(a); return copy; } int main() { A a1; A a2 = Func(a1); cout << a1._count1 << endl; cout << a2._count1 << endl; cout << a1._count2 << endl; cout << a2._count2 << endl; cout << A::_count1 << endl; cout << A::_count2 << endl; cout << a1.GetCount1() << endl; cout << a2.GetCount2() << endl; cout << A::GetCount1() << endl; cout << A::GetCount2() << endl; system("pause"); return 0; }
1
1
3
3
1
3
1
3
1
3
請按任意鍵繼續(xù). . .
1.6:C++11成員初始化新玩法
class B { public: B(int b = 0) :_b(b) {} int _b; }; class A { public: //A()//其實是編譯器自己生產(chǎn)的默認構造函數(shù)用缺省值初始化 // :a(10) // , b(20) // , p((int*)malloc(4)) //{} void Print() { cout << a << endl; cout << b._b << endl; cout << p << endl; cout << n << endl; } private: // 非靜態(tài)成員變量,可以在成員聲明時給缺省值。 int a = 10; B b = 20;//單參數(shù)的構造函數(shù),支持隱式類型的轉換 int* p = (int*)malloc(4); static int n; //非靜態(tài)成員變量定義在構造函數(shù) //靜態(tài)在類外 }; int A::n = 0; int main() { A a; a.Print(); system("pause"); return 0; }
二:友元
在程序里,有些私有屬性 也想讓類外特殊的一些函數(shù)或者類進行訪問,就需要用到友元的技術
友元的目的就是讓一個函數(shù)或者類 訪問另一個類中私有成員
友元的關鍵字為friend
友元分為:
- 友元函數(shù)
- 友元類
友元的三種實現(xiàn):
全局函數(shù)做友元
類做友元
成員函數(shù)做友元
2.1:全局函數(shù)做友元
??說明:友元函數(shù)可以直接訪問類的私有成員,它是定義在類外部的普通成員函數(shù),不屬于任何類,但需要在類的內(nèi)部聲明,聲明的時候需要加friend關鍵字。
class Building { //告訴編譯器 goodGay全局函數(shù) 是 Building類的好朋友,可以訪問類中的私有內(nèi)容 friend void goodGay(Building * building); public: Building(){ this->m_SittingRoom = "客廳"; this->m_BedRoom = "臥室"; } public: string m_SittingRoom; //客廳 private: string m_BedRoom; //臥室 }; void goodGay(Building * building){ cout << "好基友正在訪問: " << building->m_SittingRoom << endl; cout << "好基友正在訪問: " << building->m_BedRoom << endl; } void test01(){ Building b; goodGay(&b); } int main(){ test01(); system("pause"); return 0; }
代碼解釋:如上述代碼中,我們需要告訴編譯器 goodGay全局函數(shù) 是 Building類的好朋友,可以訪問類中的私有內(nèi)容
2.2:類做友元
友元類的所有成員函數(shù)都可以是另一個類的友元函數(shù),都可以訪問另一個類的非公有成員。
- 友元關系是單向的,不具有交換性。
- 友元關系不可以傳遞。如果B是A的友元,C是B的友元,但是不可以說C是A的友元。
代碼示例:
class Building; class goodGay { public: goodGay(); void visit(); private: Building *building; }; class Building { //告訴編譯器 goodGay類是Building類的好朋友,可以訪問到Building類中私有內(nèi)容 friend class goodGay; public: Building(); public: string m_SittingRoom; //客廳 private: string m_BedRoom;//臥室 }; Building::Building(){ this->m_SittingRoom = "客廳"; this->m_BedRoom = "臥室"; } goodGay::goodGay(){ building = new Building; } void goodGay::visit(){ cout << "好基友正在訪問" << building->m_SittingRoom << endl; cout << "好基友正在訪問" << building->m_BedRoom << endl; } void test01(){ goodGay gg; gg.visit(); } int main(){ test01(); system("pause"); return 0; }
代碼解釋:如上述代碼中,我們需要告訴編譯器 告訴編譯器 goodGay類是Building類的好朋友,可以訪問到Building類中私有內(nèi)容
2.3:成員函數(shù)做友元
一個類的成員函數(shù)做另一個類的友元。
代碼示例:
class Building;//提前聲明 class goodGay { public: goodGay(); void visit(); //只讓visit函數(shù)作為Building的好朋友,可以發(fā)訪問Building中私有內(nèi)容 void visit2(); private: Building *building; }; class Building { //告訴編譯器 goodGay類中的visit成員函數(shù) 是Building好朋友,可以訪問私有內(nèi)容 friend void goodGay::visit(); public: Building(); public: string m_SittingRoom; //客廳 private: string m_BedRoom;//臥室 }; Building::Building(){ this->m_SittingRoom = "客廳"; this->m_BedRoom = "臥室"; } goodGay::goodGay(){ building = new Building; } void goodGay::visit(){ cout << "好基友正在訪問" << building->m_SittingRoom << endl; cout << "好基友正在訪問" << building->m_BedRoom << endl; } void goodGay::visit2(){ cout << "好基友正在訪問" << building->m_SittingRoom << endl; //cout << "好基友正在訪問" << building->m_BedRoom << endl; } void test01(){ goodGay gg; gg.visit(); } int main(){ test01(); system("pause"); return 0; }
代碼解釋:如上述代碼中,我們需要告訴編譯器 goodGay類中的visit成員函數(shù) 是Building好朋友,可以訪問私有內(nèi)容
三:內(nèi)部類
3.1:概念
概念:如果一個類定義在另一個類的內(nèi)部,這個類就叫內(nèi)部類。注意此時的內(nèi)部類是一個獨立的類,它不屬于外部類。更不可以通過外部類的對象去調用內(nèi)部類。外部類對內(nèi)部類沒有任何的訪問權限。
??下面我們看一段代碼:
// 內(nèi)部類 class A { private: static int k; int h; public: // 內(nèi)部類 class B // B天生就是A的友元 { public: void foo(const A& a) { cout << k << endl;//OK cout << a.h << endl;//OK } private: int _b; }; // A不是B的友元 /*void Print(const B& b) { b._b = 0; }*/ }; int A::k = 1; int main() { A aa; cout << sizeof(A) << endl; A::B bb; return 0; }
代碼解釋:如上述代碼中,對于此處的內(nèi)部類,B天生就是A的友元,所以在B類中可以訪問A類的私有成員,但是A不是B的友元。如果內(nèi)部類是公有屬性的話,我們還可以實例化內(nèi)部類對象。
3.2:特性
??????特性:
- 內(nèi)部類可以定義在外部類的public、protected、private都是可以的。
- 注意內(nèi)部類可以直接訪問外部類中的static、枚舉成員,不需要外部類的對象/類名。
- sizeof(外部類) = 外部類,和內(nèi)部類沒有任何關系。
到此這篇關于C++類與對象深入之靜態(tài)成員與友元及內(nèi)部類詳解的文章就介紹到這了,更多相關C++類與對象內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!
相關文章
VSCode 使用 Code Runner 插件無法編譯運行文件名帶空格的文件問題
這篇文章主要介紹了VSCode 使用 Code Runner 插件無法編譯運行文件名帶空格的文件問題,本文通過圖文實例相結合給大家介紹的非常詳細,需要的朋友可以參考下2021-07-07C/C++?Qt?Tree與Tab組件實現(xiàn)分頁菜單功能
這篇文章主要介紹了C/C++?Qt?Tree與Tab組件實現(xiàn)分頁菜單功能,實現(xiàn)一個類似于樹形菜單欄的功能,當用戶點擊菜單欄中的選項時則會跳轉到不同的頁面上,本文簡單給大家分享實現(xiàn)代碼,感興趣的朋友跟隨小編一起看看吧2021-11-11怎么實現(xiàn)類的成員函數(shù)作為回調函數(shù)
不使用成員函數(shù),為了訪問類的成員變量,可以使用友元操作符(friend),在C++中將該函數(shù)說明為類的友元即可2013-10-10如何使用arm-none-eabi-gcc編譯器搭建STM32的Vscode開發(fā)環(huán)境
這篇文章主要介紹了使用arm-none-eabi-gcc編譯器搭建STM32的Vscode開發(fā)環(huán)境,本文給大家介紹的非常詳細,對大家的學習或工作具有一定的參考借鑒價值,需要的朋友可以參考下2023-07-07