C++類(lèi)與對(duì)象深入之靜態(tài)成員與友元及內(nèi)部類(lèi)詳解
一:靜態(tài)成員
靜態(tài)成員就是在成員變量和成員函數(shù)前加上關(guān)鍵字static,稱(chēng)為靜態(tài)成員。C++里面盡量用靜態(tài)成員變量代替全局變量。
1.1:靜態(tài)成員分類(lèi)
1?靜態(tài)成員變量:
- 所有對(duì)象共享同一份數(shù)據(jù)
- 在編譯階段分配內(nèi)存
- 類(lèi)內(nèi)聲明,類(lèi)外初始化
靜態(tài)成員函數(shù)
- 所有對(duì)象共享同一個(gè)函數(shù)
- 靜態(tài)成員函數(shù)只能訪(fǎng)問(wèn)靜態(tài)成員變量
1.2:靜態(tài)成員變量
class Person
{
public:
static int m_A; //靜態(tài)成員變量
private:
static int m_B; //靜態(tài)成員變量也是有訪(fǎng)問(wèn)權(quán)限的
};
int Person::m_A = 10;
int Person::m_B = 10;
void test01()
{
//靜態(tài)成員變量?jī)煞N訪(fǎng)問(wèn)方式
//1、通過(guò)對(duì)象
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、通過(guò)類(lèi)名
cout << "m_A = " << Person::m_A << endl;
//cout << "m_B = " << Person::m_B << endl; //私有權(quán)限訪(fǎng)問(wèn)不到
}
int main() {
test01();
system("pause");
return 0;
}
代碼解釋?zhuān)荷鲜龃a我們主要驗(yàn)證了利用兩種方式來(lái)訪(fǎng)問(wèn)靜態(tài)成員變量,以及靜態(tài)成員變量屬于整個(gè)類(lèi),屬于類(lèi)的所有對(duì)象

1.3:靜態(tài)成員函數(shù)
class Person
{
public:
static void func()
{
cout << "func調(diào)用" << endl;
m_A = 100;
//m_B = 100; //錯(cuò)誤,不可以訪(fǎng)問(wèn)非靜態(tài)成員變量
}
static int m_A; //靜態(tài)成員變量
int m_B; //
private:
//靜態(tài)成員函數(shù)也是有訪(fǎng)問(wèn)權(quán)限的
static void func2()
{
cout << "func2調(diào)用" << endl;
}
};
int Person::m_A = 10;
void test01()
{
//靜態(tài)成員變量?jī)煞N訪(fǎng)問(wèn)方式
//1、通過(guò)對(duì)象
Person p1;
p1.func();
//2、通過(guò)類(lèi)名
Person::func();
//Person::func2(); //私有權(quán)限訪(fǎng)問(wèn)不到
}
int main() {
test01();
system("pause");
return 0;
}代碼解釋?zhuān)荷鲜龃a我們主要驗(yàn)證了利用兩種方式來(lái)訪(fǎng)問(wèn)靜態(tài)成員函數(shù),利用對(duì)象訪(fǎng)問(wèn)和利用類(lèi)名訪(fǎng)問(wèn),以及靜態(tài)成員函數(shù)只可以訪(fǎng)問(wèn)靜態(tài)成員變量

??????:為什么不可以訪(fǎng)問(wèn)非靜態(tài)成員?
??因?yàn)闆](méi)有this指針
1.4:總結(jié)特性
- 靜態(tài)成員為所有類(lèi)對(duì)象所共享,不屬于某個(gè)具體的類(lèi)實(shí)例
- 靜態(tài)成員變量必須在類(lèi)外定義,定義時(shí)不加static關(guān)鍵字
- 類(lèi)靜態(tài)成員類(lèi)名::靜態(tài)成員或者對(duì)象.靜態(tài)成員來(lái)訪(fǎng)問(wèn)
- 靜態(tài)成員函數(shù)沒(méi)有隱含的this指針,不可以訪(fǎng)問(wèn)任何非靜態(tài)成員
- 靜態(tài)成員和類(lèi)的普通成員也一樣,也有三種訪(fǎng)問(wèn)權(quán)限,也可以有返回值。
1.5:試題示例
?實(shí)現(xiàn)一個(gè)類(lèi),計(jì)算程序中創(chuàng)建了多少個(gè)類(lèi)對(duì)象
class A
{
public:
A(){
++_count1;
}
A(const A& aa){
++_count2;
}
// 成員函數(shù)也可以是靜態(tài),static成員函數(shù)沒(méi)有this指針
static int GetCount1(){
return _count1;
}
static int GetCount2(){
return _count2;
}
//private:
// 靜態(tài)成員變量屬于整個(gè)類(lèi),所以類(lèi)的所有對(duì)象
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
請(qǐng)按任意鍵繼續(xù). . .
1.6:C++11成員初始化新玩法
class B
{
public:
B(int b = 0)
:_b(b)
{}
int _b;
};
class A
{
public:
//A()//其實(shí)是編譯器自己生產(chǎn)的默認(rèn)構(gòu)造函數(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)成員變量,可以在成員聲明時(shí)給缺省值。
int a = 10;
B b = 20;//單參數(shù)的構(gòu)造函數(shù),支持隱式類(lèi)型的轉(zhuǎn)換
int* p = (int*)malloc(4);
static int n;
//非靜態(tài)成員變量定義在構(gòu)造函數(shù)
//靜態(tài)在類(lèi)外
};
int A::n = 0;
int main()
{
A a;
a.Print();
system("pause");
return 0;
}二:友元
在程序里,有些私有屬性 也想讓類(lèi)外特殊的一些函數(shù)或者類(lèi)進(jìn)行訪(fǎng)問(wèn),就需要用到友元的技術(shù)
友元的目的就是讓一個(gè)函數(shù)或者類(lèi) 訪(fǎng)問(wèn)另一個(gè)類(lèi)中私有成員
友元的關(guān)鍵字為friend
友元分為:
- 友元函數(shù)
- 友元類(lèi)
友元的三種實(shí)現(xiàn):
全局函數(shù)做友元
類(lèi)做友元
成員函數(shù)做友元
2.1:全局函數(shù)做友元
??說(shuō)明:友元函數(shù)可以直接訪(fǎng)問(wèn)類(lèi)的私有成員,它是定義在類(lèi)外部的普通成員函數(shù),不屬于任何類(lèi),但需要在類(lèi)的內(nèi)部聲明,聲明的時(shí)候需要加friend關(guān)鍵字。
class Building
{
//告訴編譯器 goodGay全局函數(shù) 是 Building類(lèi)的好朋友,可以訪(fǎng)問(wèn)類(lèi)中的私有內(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 << "好基友正在訪(fǎng)問(wèn): " << building->m_SittingRoom << endl;
cout << "好基友正在訪(fǎng)問(wèn): " << building->m_BedRoom << endl;
}
void test01(){
Building b;
goodGay(&b);
}
int main(){
test01();
system("pause");
return 0;
}代碼解釋?zhuān)喝缟鲜龃a中,我們需要告訴編譯器 goodGay全局函數(shù) 是 Building類(lèi)的好朋友,可以訪(fǎng)問(wèn)類(lèi)中的私有內(nèi)容
2.2:類(lèi)做友元
友元類(lèi)的所有成員函數(shù)都可以是另一個(gè)類(lèi)的友元函數(shù),都可以訪(fǎng)問(wèn)另一個(gè)類(lèi)的非公有成員。
- 友元關(guān)系是單向的,不具有交換性。
- 友元關(guān)系不可以傳遞。如果B是A的友元,C是B的友元,但是不可以說(shuō)C是A的友元。
代碼示例:
class Building;
class goodGay
{
public:
goodGay();
void visit();
private:
Building *building;
};
class Building
{
//告訴編譯器 goodGay類(lèi)是Building類(lèi)的好朋友,可以訪(fǎng)問(wèn)到Building類(lèi)中私有內(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 << "好基友正在訪(fǎng)問(wèn)" << building->m_SittingRoom << endl;
cout << "好基友正在訪(fǎng)問(wèn)" << building->m_BedRoom << endl;
}
void test01(){
goodGay gg;
gg.visit();
}
int main(){
test01();
system("pause");
return 0;
}代碼解釋?zhuān)喝缟鲜龃a中,我們需要告訴編譯器 告訴編譯器 goodGay類(lèi)是Building類(lèi)的好朋友,可以訪(fǎng)問(wèn)到Building類(lèi)中私有內(nèi)容
2.3:成員函數(shù)做友元
一個(gè)類(lèi)的成員函數(shù)做另一個(gè)類(lèi)的友元。
代碼示例:
class Building;//提前聲明
class goodGay
{
public:
goodGay();
void visit(); //只讓visit函數(shù)作為Building的好朋友,可以發(fā)訪(fǎng)問(wèn)Building中私有內(nèi)容
void visit2();
private:
Building *building;
};
class Building
{
//告訴編譯器 goodGay類(lèi)中的visit成員函數(shù) 是Building好朋友,可以訪(fǎng)問(wèn)私有內(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 << "好基友正在訪(fǎng)問(wèn)" << building->m_SittingRoom << endl;
cout << "好基友正在訪(fǎng)問(wèn)" << building->m_BedRoom << endl;
}
void goodGay::visit2(){
cout << "好基友正在訪(fǎng)問(wèn)" << building->m_SittingRoom << endl;
//cout << "好基友正在訪(fǎng)問(wèn)" << building->m_BedRoom << endl;
}
void test01(){
goodGay gg;
gg.visit();
}
int main(){
test01();
system("pause");
return 0;
}代碼解釋?zhuān)喝缟鲜龃a中,我們需要告訴編譯器 goodGay類(lèi)中的visit成員函數(shù) 是Building好朋友,可以訪(fǎng)問(wèn)私有內(nèi)容
三:內(nèi)部類(lèi)
3.1:概念
概念:如果一個(gè)類(lèi)定義在另一個(gè)類(lèi)的內(nèi)部,這個(gè)類(lèi)就叫內(nèi)部類(lèi)。注意此時(shí)的內(nèi)部類(lèi)是一個(gè)獨(dú)立的類(lèi),它不屬于外部類(lèi)。更不可以通過(guò)外部類(lèi)的對(duì)象去調(diào)用內(nèi)部類(lèi)。外部類(lèi)對(duì)內(nèi)部類(lèi)沒(méi)有任何的訪(fǎng)問(wèn)權(quán)限。
??下面我們看一段代碼:
// 內(nèi)部類(lèi)
class A
{
private:
static int k;
int h;
public:
// 內(nèi)部類(lè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;
}
代碼解釋?zhuān)喝缟鲜龃a中,對(duì)于此處的內(nèi)部類(lèi),B天生就是A的友元,所以在B類(lèi)中可以訪(fǎng)問(wèn)A類(lèi)的私有成員,但是A不是B的友元。如果內(nèi)部類(lèi)是公有屬性的話(huà),我們還可以實(shí)例化內(nèi)部類(lèi)對(duì)象。
3.2:特性
??????特性:
- 內(nèi)部類(lèi)可以定義在外部類(lèi)的public、protected、private都是可以的。
- 注意內(nèi)部類(lèi)可以直接訪(fǎng)問(wèn)外部類(lèi)中的static、枚舉成員,不需要外部類(lèi)的對(duì)象/類(lèi)名。
- sizeof(外部類(lèi)) = 外部類(lèi),和內(nèi)部類(lèi)沒(méi)有任何關(guān)系。
到此這篇關(guān)于C++類(lèi)與對(duì)象深入之靜態(tài)成員與友元及內(nèi)部類(lèi)詳解的文章就介紹到這了,更多相關(guān)C++類(lèi)與對(duì)象內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
- C++類(lèi)與對(duì)象深入之構(gòu)造函數(shù)與析構(gòu)函數(shù)詳解
- C++類(lèi)與對(duì)象深入之引用與內(nèi)聯(lián)函數(shù)與auto關(guān)鍵字及for循環(huán)詳解
- C++類(lèi)與對(duì)象深入之運(yùn)算符重載與const及初始化列表詳解
- C++簡(jiǎn)單又輕松的講解類(lèi)和對(duì)象中友元函數(shù)
- C++全面精通類(lèi)與對(duì)象
- C++深入刨析類(lèi)與對(duì)象的使用
- C++淺析類(lèi)與對(duì)象的基礎(chǔ)
- C++淺析類(lèi)與對(duì)象基礎(chǔ)點(diǎn)
相關(guān)文章
VSCode 使用 Code Runner 插件無(wú)法編譯運(yùn)行文件名帶空格的文件問(wèn)題
這篇文章主要介紹了VSCode 使用 Code Runner 插件無(wú)法編譯運(yùn)行文件名帶空格的文件問(wèn)題,本文通過(guò)圖文實(shí)例相結(jié)合給大家介紹的非常詳細(xì),需要的朋友可以參考下2021-07-07
C語(yǔ)言 詳細(xì)解析時(shí)間復(fù)雜度與空間復(fù)雜度
算法復(fù)雜度分為時(shí)間復(fù)雜度和空間復(fù)雜度。其作用: 時(shí)間復(fù)雜度是度量算法執(zhí)行的時(shí)間長(zhǎng)短;而空間復(fù)雜度是度量算法所需存儲(chǔ)空間的大小2022-04-04
C/C++?Qt?Tree與Tab組件實(shí)現(xiàn)分頁(yè)菜單功能
這篇文章主要介紹了C/C++?Qt?Tree與Tab組件實(shí)現(xiàn)分頁(yè)菜單功能,實(shí)現(xiàn)一個(gè)類(lèi)似于樹(shù)形菜單欄的功能,當(dāng)用戶(hù)點(diǎn)擊菜單欄中的選項(xiàng)時(shí)則會(huì)跳轉(zhuǎn)到不同的頁(yè)面上,本文簡(jiǎn)單給大家分享實(shí)現(xiàn)代碼,感興趣的朋友跟隨小編一起看看吧2021-11-11
詳解如何實(shí)現(xiàn)C++虛函數(shù)調(diào)用匯編代碼
多態(tài)是C++中最重要的特性之一,對(duì)虛函數(shù)的調(diào)用在C++代碼中是隨處可見(jiàn)的,本篇文章我們?cè)敿?xì)探討一下,感興趣的朋友快來(lái)看看吧2021-11-11
怎么實(shí)現(xiàn)類(lèi)的成員函數(shù)作為回調(diào)函數(shù)
不使用成員函數(shù),為了訪(fǎng)問(wèn)類(lèi)的成員變量,可以使用友元操作符(friend),在C++中將該函數(shù)說(shuō)明為類(lèi)的友元即可2013-10-10
如何使用arm-none-eabi-gcc編譯器搭建STM32的Vscode開(kāi)發(fā)環(huán)境
這篇文章主要介紹了使用arm-none-eabi-gcc編譯器搭建STM32的Vscode開(kāi)發(fā)環(huán)境,本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2023-07-07

