網站首頁 編程語言 正文
一:靜態成員
靜態成員就是在成員變量和成員函數前加上關鍵字static,稱為靜態成員。C++里面盡量用靜態成員變量代替全局變量。
1.1:靜態成員分類
1?靜態成員變量:
- 所有對象共享同一份數據
- 在編譯階段分配內存
- 類內聲明,類外初始化
靜態成員函數
- 所有對象共享同一個函數
- 靜態成員函數只能訪問靜態成員變量
1.2:靜態成員變量
class Person
{
public:
static int m_A; //靜態成員變量
private:
static int m_B; //靜態成員變量也是有訪問權限的
};
int Person::m_A = 10;
int Person::m_B = 10;
void test01()
{
//靜態成員變量兩種訪問方式
//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; //共享同一份數據
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;
}
代碼解釋:上述代碼我們主要驗證了利用兩種方式來訪問靜態成員變量,以及靜態成員變量屬于整個類,屬于類的所有對象
1.3:靜態成員函數
class Person
{
public:
static void func()
{
cout << "func調用" << endl;
m_A = 100;
//m_B = 100; //錯誤,不可以訪問非靜態成員變量
}
static int m_A; //靜態成員變量
int m_B; //
private:
//靜態成員函數也是有訪問權限的
static void func2()
{
cout << "func2調用" << endl;
}
};
int Person::m_A = 10;
void test01()
{
//靜態成員變量兩種訪問方式
//1、通過對象
Person p1;
p1.func();
//2、通過類名
Person::func();
//Person::func2(); //私有權限訪問不到
}
int main() {
test01();
system("pause");
return 0;
}
代碼解釋:上述代碼我們主要驗證了利用兩種方式來訪問靜態成員函數,利用對象訪問和利用類名訪問,以及靜態成員函數只可以訪問靜態成員變量
??????:為什么不可以訪問非靜態成員?
??因為沒有this指針
1.4:總結特性
- 靜態成員為所有類對象所共享,不屬于某個具體的類實例
- 靜態成員變量必須在類外定義,定義時不加static關鍵字
- 類靜態成員類名::靜態成員或者對象.靜態成員來訪問
- 靜態成員函數沒有隱含的this指針,不可以訪問任何非靜態成員
- 靜態成員和類的普通成員也一樣,也有三種訪問權限,也可以有返回值。
1.5:試題示例
?實現一個類,計算程序中創建了多少個類對象
class A
{
public:
A(){
++_count1;
}
A(const A& aa){
++_count2;
}
// 成員函數也可以是靜態,static成員函數沒有this指針
static int GetCount1(){
return _count1;
}
static int GetCount2(){
return _count2;
}
//private:
// 靜態成員變量屬于整個類,所以類的所有對象
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
請按任意鍵繼續. . .
1.6:C++11成員初始化新玩法
class B
{
public:
B(int b = 0)
:_b(b)
{}
int _b;
};
class A
{
public:
//A()//其實是編譯器自己生產的默認構造函數用缺省值初始化
// :a(10)
// , b(20)
// , p((int*)malloc(4))
//{}
void Print()
{
cout << a << endl;
cout << b._b << endl;
cout << p << endl;
cout << n << endl;
}
private:
// 非靜態成員變量,可以在成員聲明時給缺省值。
int a = 10;
B b = 20;//單參數的構造函數,支持隱式類型的轉換
int* p = (int*)malloc(4);
static int n;
//非靜態成員變量定義在構造函數
//靜態在類外
};
int A::n = 0;
int main()
{
A a;
a.Print();
system("pause");
return 0;
}
二:友元
在程序里,有些私有屬性 也想讓類外特殊的一些函數或者類進行訪問,就需要用到友元的技術
友元的目的就是讓一個函數或者類 訪問另一個類中私有成員
友元的關鍵字為friend
友元分為:
- 友元函數
- 友元類
友元的三種實現:
全局函數做友元
類做友元
成員函數做友元
2.1:全局函數做友元
??說明:友元函數可以直接訪問類的私有成員,它是定義在類外部的普通成員函數,不屬于任何類,但需要在類的內部聲明,聲明的時候需要加friend關鍵字。
class Building
{
//告訴編譯器 goodGay全局函數 是 Building類的好朋友,可以訪問類中的私有內容
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全局函數 是 Building類的好朋友,可以訪問類中的私有內容
2.2:類做友元
友元類的所有成員函數都可以是另一個類的友元函數,都可以訪問另一個類的非公有成員。
- 友元關系是單向的,不具有交換性。
- 友元關系不可以傳遞。如果B是A的友元,C是B的友元,但是不可以說C是A的友元。
代碼示例:
class Building;
class goodGay
{
public:
goodGay();
void visit();
private:
Building *building;
};
class Building
{
//告訴編譯器 goodGay類是Building類的好朋友,可以訪問到Building類中私有內容
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類中私有內容
2.3:成員函數做友元
一個類的成員函數做另一個類的友元。
代碼示例:
class Building;//提前聲明
class goodGay
{
public:
goodGay();
void visit(); //只讓visit函數作為Building的好朋友,可以發訪問Building中私有內容
void visit2();
private:
Building *building;
};
class Building
{
//告訴編譯器 goodGay類中的visit成員函數 是Building好朋友,可以訪問私有內容
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成員函數 是Building好朋友,可以訪問私有內容
三:內部類
3.1:概念
概念:如果一個類定義在另一個類的內部,這個類就叫內部類。注意此時的內部類是一個獨立的類,它不屬于外部類。更不可以通過外部類的對象去調用內部類。外部類對內部類沒有任何的訪問權限。
??下面我們看一段代碼:
// 內部類
class A
{
private:
static int k;
int h;
public:
// 內部類
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;
}
代碼解釋:如上述代碼中,對于此處的內部類,B天生就是A的友元,所以在B類中可以訪問A類的私有成員,但是A不是B的友元。如果內部類是公有屬性的話,我們還可以實例化內部類對象。
3.2:特性
??????特性:
- 內部類可以定義在外部類的public、protected、private都是可以的。
- 注意內部類可以直接訪問外部類中的static、枚舉成員,不需要外部類的對象/類名。
- sizeof(外部類) = 外部類,和內部類沒有任何關系。
原文鏈接:https://blog.csdn.net/qq_43727529/article/details/124962793
相關推薦
- 2023-02-15 Go?Comparable?Type原理深入解析_Golang
- 2022-07-11 Python字節碼與程序執行過程詳解_python
- 2023-10-26 video標簽未自動播放,autoplay無效,video不能自動播放的原因分析
- 2023-01-02 Kotlin?FrameLayout與ViewPager2控件實現滾動廣告欄方法_Android
- 2023-04-26 Numpy對于NaN值的判斷方法_python
- 2022-11-22 Nginx?Tomcat負載均衡動靜分離原理解析_nginx
- 2024-03-10 詳解Spring Bean的生命周期
- 2022-08-19 Android實現九宮格抽獎_Android
- 最近更新
-
- window11 系統安裝 yarn
- 超詳細win安裝深度學習環境2025年最新版(
- Linux 中運行的top命令 怎么退出?
- MySQL 中decimal 的用法? 存儲小
- get 、set 、toString 方法的使
- @Resource和 @Autowired注解
- Java基礎操作-- 運算符,流程控制 Flo
- 1. Int 和Integer 的區別,Jav
- spring @retryable不生效的一種
- Spring Security之認證信息的處理
- Spring Security之認證過濾器
- Spring Security概述快速入門
- Spring Security之配置體系
- 【SpringBoot】SpringCache
- Spring Security之基于方法配置權
- redisson分布式鎖中waittime的設
- maven:解決release錯誤:Artif
- restTemplate使用總結
- Spring Security之安全異常處理
- MybatisPlus優雅實現加密?
- Spring ioc容器與Bean的生命周期。
- 【探索SpringCloud】服務發現-Nac
- Spring Security之基于HttpR
- Redis 底層數據結構-簡單動態字符串(SD
- arthas操作spring被代理目標對象命令
- Spring中的單例模式應用詳解
- 聊聊消息隊列,發送消息的4種方式
- bootspring第三方資源配置管理
- GIT同步修改后的遠程分支