Halo,這里是Ppeua。平時(shí)主要更新C語言,C++,數(shù)據(jù)結(jié)構(gòu)算法…感興趣就關(guān)注我bua!

0. 初始化列表
這是一個(gè)C++的默認(rèn)構(gòu)造函數(shù)
class Date{
public:
Date(int year,int month,int day)
{
_year=year;
_month=month;
_day=day;
}
private:
int _year;
int _month;
int _day;
};
雖然我們大多時(shí)候混淆初始化與賦值的概念,但在這里,構(gòu)造函數(shù)體中只能成為賦值,因?yàn)槌跏蓟荒艹跏蓟淮?,而賦值可以賦值多次。那么在哪里進(jìn)行初始化呢?可能會說在定義時(shí)直接初始化,這在日期類中是可以的,但在這種情況當(dāng)中,顯然是不可以的了
class A{
private:
int __a;
};
class B{
private:
int &_ref;
const int _ci;
};
根據(jù)前面所學(xué),引用&與限制const必須在定義時(shí)就完成初始化。那么我這里該如何初始化呢?我并沒有確定我的要使用的對象是什么。
這就是初始化列表存在的意義了:
初始化列表:以一個(gè)冒號開始,接著是一個(gè)以逗號分隔的數(shù)據(jù)成員列表,每個(gè)成員變量后面跟一個(gè)放在括號中的初始值或者表達(dá)式
class B{
public:
B(int& ref,int ci):
_ref(ref),
_ci(ci)
{
}
private:
int &_ref;
const int _ci;
};
所以,這樣解決了引用&與限定const的初始化問題:可以根據(jù)具體場景進(jìn)行初始化了。
注意:
-
每個(gè)成員變量僅能在初始化列表中出現(xiàn)一次!因?yàn)槌跏蓟荒艹跏蓟淮?/strong>
-
類中包含 引用、const成員變量及自定義類型成員(且該類沒有默認(rèn)構(gòu)造函數(shù)時(shí)),必須將其放在初始化列表中進(jìn)行初始化!
class A{ public: A(int a): __a(a) { } private: int __a; }; class B{ public: B(int a,int& ref,int ci): _a(a), _ref(ref), _ci(ci) { } private: A _a; const int _ci; int &_ref; };
例如在這個(gè)例子中,B類的屬性有三個(gè),分別對應(yīng)了自定義類型成員,引用,const的三種情況。所以需要將其放在初始化列表中進(jìn)行初始化。
其初始化順序?yàn)?,從成員屬性去找對應(yīng)的初始化列表。
這是一個(gè)初始化列表的特性,當(dāng)遇到以下這種情況的時(shí)候就需要充分考慮到這種特性。
class bug
{
public:
bug(int a):
_a1(a),
_a2(_a1)
{
}
private:
int _a2;
int _a1;
}
當(dāng)傳入的a=1時(shí)_a2與_a1的結(jié)果是什么呢?答案是a2為亂碼,a1為1,這就是因?yàn)槌跏蓟斜淼某跏蓟樞蚴歉鶕?jù)聲明順序來進(jìn)行的,所以導(dǎo)致了這個(gè)問題。
在日常中建議多用初始化列表,因?yàn)榧词乖诼暶鲿r(shí)給上初始值,之后也會調(diào)用初始化列表進(jìn)行初始化。
那初始化列表這么有用,是不是在函數(shù)體內(nèi)進(jìn)行聲明就沒有使用場景了?
class test2
{
public:
test2():
a((int *)malloc(sizeof(int)*10))
{
if(a==NULL)
{
perror("malloc,failed");
}
}
private:
int *a;
};
int main()
{
test2 a;
return 0;
}
在這段代碼中,雖然初始化列表可以完成對a的空間分配,但malloc可能存在分配失敗的問題。所以需要對其分配完的空間進(jìn)行一個(gè)檢查,此時(shí)初始化列表就不能做這件事了。
所以,初始化列表只適用于初始化變量,這一件事,其他事仍然需要放在函數(shù)體內(nèi)執(zhí)行
explicit關(guān)鍵字
class trans{
public:
trans(int a=0)
{
_a=a;
cout<<"trans()";
}
trans(const trans& T)
:_a(T._a)
{
cout<<"trans(const trans&T)";
}
void print()
{
cout<<_a<<endl;
}
private:
int _a;
};
int main()
{
trans T1(1);
trans T2=2;
const trans& T3=2;
return 0;
}
T1與T2的初始化非常的常見,前面也介紹了很多類似的用法,但需注意,T2此時(shí)有一個(gè)隱式類型轉(zhuǎn)換:
會先將內(nèi)置類型調(diào)用一次構(gòu)造函數(shù),將其變?yōu)閠rans對象,之后再調(diào)用一次初始化構(gòu)造,完成對T2的初始化。(但經(jīng)過編譯器優(yōu)化后這種行為只會出現(xiàn)一次)
所以T3為什么需要加上const?因?yàn)樵谕瓿赊D(zhuǎn)換后,臨時(shí)構(gòu)造出的trans會被銷毀,而&又不能引用一個(gè)銷毀的對象,所以需要const延長其生命周期。
當(dāng)然,我們?nèi)绻幌氚l(fā)生這種隱式類型轉(zhuǎn)換的行為,可以在構(gòu)造函數(shù)前加入 explicit的關(guān)鍵字。
class trans{
public:
explicit trans(int a=0)
{
_a=a;
cout<<"trans()";
}
trans(const trans& T)
:_a(T._a)
{
cout<<"trans(const trans&T)";
}
void print()
{
cout<<_a<<endl;
}
private:
int _a;
};
int main()
{
trans T1(1);
trans T2=2;
return 0;
}
1.Static靜態(tài)成員變量
看看以下這個(gè)程序,創(chuàng)建了多少類對象。
class sta{
public:
sta(){
_count++;
}
sta(const sta&st)
{
_count++;
}
~sta()
{
--_count;
}
static int _count;
};
int sta::_count=0;
sta aa0;
void Func()
{
static sta aa2;
cout << __LINE__ << ":" << sta::_count << endl;
sta::_count++;
}
int main()
{
cout <<__LINE__<<":"<< sta::_count << endl; // 1
sta aa1;
Func(); // 3
Func(); // 3
return 0;
}
從中可以看出static對象的作用:對于全局變量進(jìn)行了進(jìn)一步的封裝:
- 靜態(tài)成員為所有類對象所共享,不屬于某個(gè)具體的對象
- 靜態(tài)成員變量在類內(nèi)聲明,在類外定義,定義時(shí)不加static關(guān)鍵字
- 可以通過類名::變量名 或者 對象.靜態(tài)成員來訪問
- 靜態(tài)成員函數(shù)沒有this指針,所以不能訪問任何非靜態(tài)成員
- 靜態(tài)成員也是類的成員,受訪問限定符限制
一道用到了static變量特性的oj題
class sum
{
public:
sum()
{
n++;
s+=n;
}
static int s;
static int n;
};
int sum:: s=0;
int sum:: n=0;
class Solution {
public:
int Sum_Solution(int n) {
sum s1[n];
return sum::s;
}
};
2.友元
2.1.友元函數(shù)
友元函數(shù)可以直接訪問類的私有成員,使用時(shí)在類中的任意位置聲明即可,
class test0
{
public:
private:
int score=100;
};
void print(const test0& t0)
{
cout<<t0.score<<endl;
}
在這里,是無法訪問score這個(gè)變量的,因?yàn)閟core為私有成員屬性,所以無法在類外進(jìn)行訪問.但加入友元函數(shù)的聲明后可以突破這個(gè)限制
class test0
{
friend void print(const test0&t0);
public:
private:
int score=100;
};
void print(const test0& t0)
{
cout<<t0.score<<endl;
}
- 友元函數(shù)可以訪問類的私有成員和保護(hù)成員,但其不是類的成員函數(shù)
- 友元函數(shù)因?yàn)椴皇穷惖某蓡T函數(shù),沒有this指針,所以不可以且沒必要用后置const進(jìn)行修飾
- 友元函數(shù)可以在類定義的任何地方進(jìn)行聲明
- 一個(gè)函數(shù)可以與多個(gè)類達(dá)成友元關(guān)系
- 調(diào)用原理與普通函數(shù)相同
2.2.友元類
在一個(gè)類中聲明加入另一個(gè)類的友元聲明,在另一個(gè)類中即可訪問這個(gè)類受保護(hù)的成員變量.
class test0
{
friend void print(const test0&t0);
friend class test3;
public:
private:
int score=100;
};
class test3
{
public:
void print()
{
cout<<t0.score;
}
private:
test0 t0;
};
- 友元關(guān)系是單向的,test3可以訪問test0的成員變量,反之卻不可以
- 友元關(guān)系不能傳遞
3.內(nèi)部類
一個(gè)類定義定義在一個(gè)類的里面.
class A
{
public:
class B{
private:
int _b;
};
private:
static int _a1;
int _a2;
};
int A:: _a1=0;
int main()
{
return 0;
}
計(jì)算A的大小時(shí),僅計(jì)算A中的成員,例如這里sizeof(A)=4.
內(nèi)部類是外部類的友元,訪問靜態(tài)變量的時(shí)候不需要加類作用域修飾符
這里B是A的友元,但A不是B的友元
class A
{
public:
class B{
public:
void print(const A&a)
{
cout<<a._a2<<_a1;
}
private:
int _b;
};
private:
static int _a1;
int _a2;
};
4.匿名對象
當(dāng)想使用一個(gè)類中的某一個(gè)函數(shù)時(shí)可以直接使用匿名對象.
class C{
public:
void print()
{
cout<<6;
}
};
int main()
{
C a;
a.print();
C().print();
}
正常的調(diào)用需要像main中前兩行寫一樣,但加入了匿名函數(shù)的規(guī)則之后,直接按照第三個(gè)規(guī)則來寫即可.匿名函數(shù)的生命周期僅在當(dāng)前行.文章來源地址http://www.zghlxwxcb.cn/news/detail-455500.html
void print(const A&a)
{
cout<<a._a2<<_a1;
}
private:
int _b;
};
private:
static int _a1;
int _a2;
};
4.匿名對象
當(dāng)想使用一個(gè)類中的某一個(gè)函數(shù)時(shí)可以直接使用匿名對象.文章來源:http://www.zghlxwxcb.cn/news/detail-455500.html
class C{
public:
void print()
{
cout<<6;
}
};
int main()
{
C a;
a.print();
C().print();
}
正常的調(diào)用需要像main中前兩行寫一樣,但加入了匿名函數(shù)的規(guī)則之后,直接按照第三個(gè)規(guī)則來寫即可.匿名函數(shù)的生命周期僅在當(dāng)前行.
至此初始化列表,static,友元,內(nèi)部類,匿名對象的理解與使用結(jié)束
到了這里,關(guān)于【C++技能樹】類和對象的使用 --初始化列表,static,友元,內(nèi)部類,匿名對象的理解與使用的文章就介紹完了。如果您還想了解更多內(nèi)容,請?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!