目錄
前言:
一:static成員
(1)概念
(2)特性
(3)例子
二:explicit關(guān)鍵字?
三:內(nèi)部類(lèi)
(1)概念
(2)特性
(3)實(shí)例
四:匿名對(duì)象
(1)概念
(2)特性
(3)實(shí)例
五:拷貝對(duì)象時(shí)的一些編譯器優(yōu)化
(1)引入
(2)更多例子
代碼:
前言:
C++專(zhuān)欄內(nèi)容連貫,沒(méi)展開(kāi)講的重要內(nèi)容都在專(zhuān)欄往期。
為方便語(yǔ)法學(xué)習(xí),直接展開(kāi)std命名空間。
個(gè)人主頁(yè)鏈接:派小星233的博客_CSDN博客-初階數(shù)據(jù)結(jié)構(gòu),C語(yǔ)言,C++初階領(lǐng)域博主?
一:static成員
(1)概念
- 聲明為static的類(lèi)成員稱(chēng)為類(lèi)的靜態(tài)成員,用static修飾的成員變量,稱(chēng)之為靜態(tài)成員變量,靜態(tài)成員變量一定要在類(lèi)外進(jìn)行初始化
- 用static修飾的成員函數(shù),稱(chēng)之為靜態(tài)成員函數(shù)。
(2)特性
- 靜態(tài)成員為所有類(lèi)對(duì)象所共享,不屬于某個(gè)具體的對(duì)象,存放在靜態(tài)區(qū)
- 靜態(tài)成員變量必須在類(lèi)外定義,定義時(shí)不添加static關(guān)鍵字,類(lèi)中只是聲明
- 類(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)的成員,受public、protected、private 訪(fǎng)問(wèn)限定符的限制
(3)例子
問(wèn)題:實(shí)現(xiàn)一個(gè)類(lèi),計(jì)算程序中創(chuàng)建出了多少個(gè)類(lèi)對(duì)象。?
代碼:
class A
{
public:
A() //構(gòu)造
{
++_scount;
}
A(const A & t) //拷貝
{
++_scount;
}
static int GetACount()
{
return _scount;
}
private:
//聲明這個(gè)靜態(tài)變量是屬于這個(gè)類(lèi)的,沒(méi)有定義
static int _scount;
};
//定義并加域限定符(域限定也是符號(hào)表規(guī)則之一,不加的話(huà)類(lèi)中的_scout只有聲明)
int A::_scount = 0;
int main()
{
cout << A::GetACount() << endl;
A a1, a2;
A a3(a1);
//構(gòu)造了三次,屬于類(lèi)A的靜態(tài)變量加了3
cout << A::GetACount() << endl;
return 0;
}
二:explicit關(guān)鍵字?
class A
{
public:
A(int a = 0,int b = 0)
:_a(a)
,_b(b)
{}
private:
int _a;
int _b;
};
int main()
{
A a1 = 50;
return 0;
}
上面的代碼和結(jié)果說(shuō)明了這樣一個(gè)現(xiàn)象:
構(gòu)造函數(shù)不僅可以構(gòu)造與初始化對(duì)象,對(duì)于單個(gè)參數(shù)或者除第一個(gè)參數(shù)無(wú)默認(rèn)值其余均有默認(rèn)值的構(gòu)造函數(shù),還具有類(lèi)型轉(zhuǎn)換的作用。
?構(gòu)造函數(shù)的隱式轉(zhuǎn)換有的時(shí)候很靈活,有的時(shí)候卻會(huì)導(dǎo)致代碼的可讀性下降,explicit關(guān)鍵字的作用就是修飾構(gòu)造函數(shù),禁止類(lèi)型轉(zhuǎn)換。
代碼:
//這段代碼編譯不通過(guò)
class Date
{
public:
// 1. 單參構(gòu)造函數(shù),沒(méi)有使用explicit修飾,具有類(lèi)型轉(zhuǎn)換作用
// explicit修飾構(gòu)造函數(shù),禁止類(lèi)型轉(zhuǎn)換---explicit去掉之后,代碼可以通過(guò)編譯
explicit Date(int year)
:_year(year)
{}
/*
// 2. 雖然有多個(gè)參數(shù),但是創(chuàng)建對(duì)象時(shí)后兩個(gè)參數(shù)可以不傳遞,沒(méi)有使用explicit修飾,具
有類(lèi)型轉(zhuǎn)換作用
// explicit修飾構(gòu)造函數(shù),禁止類(lèi)型轉(zhuǎn)換
explicit Date(int year, int month = 1, int day = 1)
: _year(year)
, _month(month)
, _day(day)
{}
*/
Date& operator=(const Date& d)
{
if (this != &d)
{
_year = d._year;
_month = d._month;
_day = d._day;
}
return *this;
}
private:
int _year;
int _month;
int _day;
};
void Test()
{
Date d1(2022);
// 用一個(gè)整形變量給日期類(lèi)型對(duì)象賦值
//構(gòu)造函數(shù)沒(méi)用explicit修飾時(shí)實(shí)際編譯器背后會(huì)用2023構(gòu)造一個(gè)無(wú)名對(duì)象,最后用無(wú)名對(duì)象給d1對(duì)象進(jìn)行賦值
d1 = 2023;
// 將1屏蔽掉,2放開(kāi)時(shí)則編譯失敗,因?yàn)閑xplicit修飾構(gòu)造函數(shù),禁止了單參構(gòu)造函數(shù)類(lèi)型轉(zhuǎn)換的作用
}
?
?文章來(lái)源地址http://www.zghlxwxcb.cn/news/detail-497766.html
三:內(nèi)部類(lèi)
(1)概念
如果一個(gè)類(lèi)定義在另一個(gè)類(lèi)的內(nèi)部,這個(gè)內(nèi)部類(lèi)就叫做內(nèi)部類(lèi)。內(nèi)部類(lèi)是一個(gè)獨(dú)立的類(lèi),
它不屬于外部類(lèi);內(nèi)部類(lèi)就是外部類(lèi)的友元類(lèi),內(nèi)部類(lèi)可以訪(fǎng)問(wèn)外部類(lèi)中的所有成員。但是外部類(lèi)不是內(nèi)部類(lèi)的友元,不能通過(guò)外部類(lèi)的對(duì)象去訪(fǎng)問(wèn)內(nèi)部類(lèi)的成員。外部類(lèi)對(duì)內(nèi)部類(lèi)沒(méi)有任何優(yōu)越的訪(fǎng)問(wèn)權(quán)限。(C++內(nèi)部類(lèi)并不常用)
(2)特性
- 內(nèi)部類(lèi)可以定義在外部類(lèi)的public、protected、private都是可以的。(如果定義在private或者protected,則外部不可定義內(nèi)部類(lèi)的對(duì)象)
- 注意內(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)系。
(3)實(shí)例
class A
{
private:
static int k;
int _a = 0;
public:
class B // B天生就是A的友元
{
public:
void foo(const A& a)
{
//B類(lèi)是A類(lèi)友元,可以訪(fǎng)問(wèn)A
cout << k << endl;
cout << a._a << endl;
}
};
};
int A::k = 1;
int main()
{
//雖然說(shuō)類(lèi)A對(duì)類(lèi)B并沒(méi)有訪(fǎng)問(wèn)權(quán)限,但是類(lèi)B的定義是在A的域里面的
//定義類(lèi)B實(shí)例化對(duì)象時(shí)需要加上域限定符
A::B b;
A a1;
b.foo(a1);
return 0;
}
四:匿名對(duì)象
(1)概念
匿名對(duì)象指的是沒(méi)有被賦予任何名稱(chēng)的對(duì)象,它們通常是在方法調(diào)用時(shí)臨時(shí)創(chuàng)建的,并且只能被引用一次。雖然匿名對(duì)象沒(méi)有名稱(chēng),但它們?nèi)匀皇且粋€(gè)完整的對(duì)象,具有對(duì)象的所有屬性和方法。需要注意的是,由于沒(méi)有名稱(chēng),當(dāng)使用匿名對(duì)象時(shí)無(wú)法再進(jìn)行其他操作或訪(fǎng)問(wèn)該對(duì)象。
(2)特性
匿名對(duì)象沒(méi)有名字,在定義對(duì)象時(shí),不需要為其分配變量名,可以直接使用,且使用完畢后不需要釋放內(nèi)存,系統(tǒng)會(huì)自動(dòng)回收。
匿名對(duì)象一般用于臨時(shí)的對(duì)象操作,可以在一些函數(shù)中直接使用,無(wú)需定義變量。
匿名對(duì)象一般不能用于多次操作。如果需要多次操作一個(gè)對(duì)象,應(yīng)當(dāng)定義具名對(duì)象,否則代碼會(huì)難以維護(hù)。
在定義匿名對(duì)象時(shí),無(wú)法傳遞對(duì)象參數(shù)執(zhí)行對(duì)象的構(gòu)造函數(shù)。
匿名對(duì)象的生命周期只有一條語(yǔ)句。
(3)實(shí)例
代碼:
class A
{
public:
A(int a = 0)
:_a(a)
{
cout << "A(int a)" << endl;
}
~A()
{
cout << "~A()" << endl;
}
private:
int _a;
};
class Solution {
public:
int Sum_Solution(int n)
{
//這里可以實(shí)現(xiàn)一系列計(jì)算,比方求n的階乘
//…………
return n;
}
};
int main()
{
A aa1;
// 不能這么定義對(duì)象,因?yàn)榫幾g器無(wú)法識(shí)別下面是一個(gè)函數(shù)聲明,還是對(duì)象定義
//A aa1();
// 但是我們可以這么定義匿名對(duì)象,匿名對(duì)象的特點(diǎn)不用取名字,
// 但是他的生命周期只有這一行,我們可以看到下一行他就會(huì)自動(dòng)調(diào)用析構(gòu)函數(shù)
A();
A aa2(2);
// 匿名對(duì)象在這樣場(chǎng)景下就很好用
Solution().Sum_Solution(10);
return 0;
}
五:拷貝對(duì)象時(shí)的一些編譯器優(yōu)化
(1)引入
注意:這部分的優(yōu)化取決于編譯器,大部分的編譯器是存在優(yōu)化的。
?但對(duì)象復(fù)雜的類(lèi)對(duì)象,一個(gè)對(duì)象往往很大,這個(gè)時(shí)候拷貝的代價(jià)十分大,編譯器會(huì)在保證安全的情況下進(jìn)行優(yōu)化。比如:使用去A函數(shù)構(gòu)造一個(gè)對(duì)象,然后傳值返回main函數(shù)去拷貝構(gòu)造一個(gè)新對(duì)象。在未優(yōu)化的情況下,你先拷貝了一份存儲(chǔ)在預(yù)留的部分,然后在回收空間前又拷貝預(yù)留的一份到main函數(shù)棧幀中;這個(gè)行為在編譯器看來(lái)是可以?xún)?yōu)化的,于是編譯器直接拷貝了一份到main函數(shù)棧幀中,省去了在預(yù)留空間中的一次拷貝。(其他的連續(xù)拷貝也類(lèi)似)
(2)更多例子
代碼:
class A
{
public:
A(int a = 0)
:_a(a)
{
cout << "A(int a)" << endl;
}
A(const A& aa)
:_a(aa._a)
{
cout << "A(const A& aa)" << endl;
}
A& operator=(const A& aa)
{
cout << "A& operator=(const A& aa)" << endl;
if (this != &aa)
{
_a = aa._a;
}
return *this;
}
~A()
{
cout << "~A()" << endl;
}
private:
int _a;
};
void f1(A aa)
{}
A f2()
{
A aa;
return aa;
}
int main()
{
// 傳值傳參
A aa1;
f1(aa1);
cout << endl;
// 傳值返回
f2();
cout << endl;
// 隱式類(lèi)型,連續(xù)構(gòu)造+拷貝構(gòu)造->優(yōu)化為直接構(gòu)造
f1(1);
// 一個(gè)表達(dá)式中,連續(xù)構(gòu)造+拷貝構(gòu)造->優(yōu)化為一個(gè)構(gòu)造
f1(A(2));
cout << endl;
// 一個(gè)表達(dá)式中,連續(xù)拷貝構(gòu)造+拷貝構(gòu)造->優(yōu)化一個(gè)拷貝構(gòu)造
A aa2 = f2();
cout << endl;
// 一個(gè)表達(dá)式中,連續(xù)拷貝構(gòu)造+賦值重載->無(wú)法優(yōu)化
aa1 = f2();
cout << endl;
return 0;
}
文章來(lái)源:http://www.zghlxwxcb.cn/news/detail-497766.html
?
到了這里,關(guān)于C++入門(mén):類(lèi)和對(duì)象(后)的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!