面向?qū)ο?/h2>
訪問控制與封裝
- 定義在public說明符之后的成員可在整個程序內(nèi)被訪問。
- 定義在private之后的成員可以被類的成員函數(shù)訪問。
struct 或 class 關(guān)鍵字型豁,定義的類的所有成員都是public的時候,那么使用struct祥诽。反之辣垒,如果希望成員是private的南吮,使用class蜜猾。
友元
struct 或 class 關(guān)鍵字型豁,定義的類的所有成員都是public的時候,那么使用struct祥诽。反之辣垒,如果希望成員是private的南吮,使用class蜜猾。
類想把一個函數(shù)作為它的友元辱姨,只需要增加一個friend關(guān)鍵字開始的函數(shù)聲明語句即可柿菩。
友元聲明只能出現(xiàn)在類定義的內(nèi)部,但是在類內(nèi)出現(xiàn)的具體位置不限雨涛,友元不是類的成員枢舶,不受它所在區(qū)域訪問控制級別的約束。
封裝的益處:
- 確保用戶代碼不會無意間破壞封裝對象的狀態(tài)
- 被封裝地類的具體實(shí)現(xiàn)細(xì)節(jié)可以隨時改變替久,而無須調(diào)整用戶級別的代碼凉泄。
友元的聲明
? 友元的聲明僅僅指定了訪問的權(quán)限。而非一個通常意義上的函數(shù)聲明蚯根,如果我們希望類的用戶能夠調(diào)用某個友元函數(shù)后众,那么我們就必須在友員聲明之外再專門對函數(shù)進(jìn)行一次聲明。
類之間的友元關(guān)系
? 如果一個類指定了友元類,則友元類的成員函數(shù)可以訪問此類包括非公有成員在內(nèi)的所有成員蒂誉。
函數(shù)重載和友元
? 如果一個類想把一組重載函數(shù)聲明成它的友元教藻,它需要對這組函數(shù)中的每個分別聲明。
令成員作為內(nèi)聯(lián)函數(shù)
class Screen {
public:
typedef std::string::size_type pos;
Screen() = default;
Screen(pos ht, pos wd, char c): height(ht), width(wd), contents(ht * wd, c) {}
char get() const {return contents[cursor]; } // 隱式內(nèi)聯(lián)
inline char get(pos ht, pos wd) const; // 顯式內(nèi)聯(lián)
Screen &move(pos r, pos c); // 能在之后設(shè)為內(nèi)聯(lián)
private:
pos cursor = 0;
pos height = 0, width = 0;
std::string contents;
}
inline &Screen::move(pos r, pos c) // 可以在函數(shù)的定義處指定inline
{
pos row = r * width;
cursor = row + c;
return *this; //以左值形式返回對象
}
char Screen::get(pos r, pos c) const // 在類的內(nèi)部聲明成inline
{
pos row = r * width;
return contents[row + c];
}
隱式的類類型轉(zhuǎn)換
另一個是從istream到Sales_data的轉(zhuǎn)換:
// 使用istream構(gòu)造函數(shù)創(chuàng)建一個函數(shù)傳遞給combine
item.combine(cin)
這段代碼隱式的把cin 轉(zhuǎn)換成 Sales_data, 這個轉(zhuǎn)換執(zhí)行了一個istream 的 Sales_data 構(gòu)造函數(shù)右锨,該構(gòu)造函數(shù)通過讀取標(biāo)準(zhǔn)輸入創(chuàng)建了一個臨時的Sales_data對象括堤,隨后將得到的對象傳遞給combine。
抑制構(gòu)造函數(shù)定義的隱式轉(zhuǎn)換
在要求隱式轉(zhuǎn)換的程序上下文中绍移,我們可以通過將構(gòu)造函數(shù)聲明為explicit加以阻止:
class Sales_data {
public:
Sales_data() = default;
Sales_data(const std::string &s, unsigned n, double p):bookNo(s), units_sold(n),revenue(p*n) {}
explicit Sales_data(const std::string &s):bookNo(s){}
explicit Sales_data(std::istream&);
}
此時沒有任何構(gòu)造函數(shù)能用于隱式轉(zhuǎn)換的創(chuàng)建Sales_data 對象痊臭, 之前的用法item.combine(cin) 無法通過編譯;
關(guān)鍵字explicit 只對一個實(shí)參的構(gòu)造函數(shù)有效登夫。需要多個實(shí)參的構(gòu)造函數(shù)不能用于執(zhí)行隱式轉(zhuǎn)換,所以無須將這些構(gòu)造函數(shù)指定為explicit的允趟。只能在類內(nèi)聲明構(gòu)造函數(shù)時使用explicit關(guān)鍵字恼策,在外部定義時不能重復(fù)。
explicit 構(gòu)造函數(shù)只能用于直接初始化而不能使用explicit 構(gòu)造函數(shù)來執(zhí)行拷貝形式的初始化潮剪。
盡管編譯器不會將explicit 的構(gòu)造函數(shù)用于隱式轉(zhuǎn)換過程涣楷,但是我們可以使用這樣的構(gòu)造函數(shù)顯示的強(qiáng)制進(jìn)行轉(zhuǎn)化
item.combine(static_cast<Sales_data>(cin));
// 正確,static_cast 可以使用 explicit 的構(gòu)造函數(shù)抗碰。
聚合類
要求類所有成員都是public
沒有定義任何構(gòu)造函數(shù)
沒有類內(nèi)初始值
-
沒有基類狮斗,沒有virtual函數(shù)
struct Data { int ival; string s; } Data val1 = {0, "Anna"};
字面值常量類
- 數(shù)據(jù)成員必須是字面值類型
- 類必須是含有一個constexpr構(gòu)造函數(shù)
- 類必須使用析構(gòu)函數(shù)的默認(rèn)定義,該成員負(fù)責(zé)銷毀類的對象弧蝇。
- 如果一個數(shù)據(jù)成員含有類內(nèi)初始值碳褒,則內(nèi)置類型成員的初值必須是一條常量表達(dá)式;
類的靜態(tài)成員
聲明靜態(tài)成員
靜態(tài)成員可以是public的 或者是 private 的看疗,靜態(tài)數(shù)據(jù)成員的類型可以使常量沙峻,引用,指針两芳,類類型等摔寨。
類的靜態(tài)成員存在于任何對象之外,對象中不包含任何與靜態(tài)數(shù)據(jù)成員有關(guān)的數(shù)據(jù)怖辆。
靜態(tài)成員函數(shù)也不與任何對象綁定在一起是复,它們不包含this指針。作為結(jié)果竖螃,靜態(tài)成員函數(shù)不能聲明為const的淑廊,而且我們也不能再static 函數(shù)體內(nèi)使用this指針。
在類的外部定義靜態(tài)成員時斑鼻,不能重復(fù)static關(guān)鍵字蒋纬,該關(guān)鍵字只能出現(xiàn)在類內(nèi)部的聲明語句中。
因?yàn)殪o態(tài)數(shù)據(jù)成員不屬于類的任何一個對象,所以它們不是在創(chuàng)建類的對象時被定義的蜀备。這意味著它們不是由類的構(gòu)造函數(shù)初始化的关摇。而且一般來說我們不能再類的內(nèi)部初始化靜態(tài)成員,相反的碾阁,必須在類的外部定義和初始化每個靜態(tài)成員输虱。
靜態(tài)數(shù)據(jù)成員和全局變量類似,一旦被定義脂凶,就存在于程序的整個生命周期
靜態(tài)數(shù)據(jù)成員可以作為默認(rèn)實(shí)參宪睹,非靜態(tài)數(shù)據(jù)成員不能。
靜態(tài)成員的類內(nèi)初始化
靜態(tài)成員可以通過const整數(shù)類型的類內(nèi)初始值進(jìn)行初始化蚕钦。要求靜態(tài)成員必須是字面值常量類型的constexpr亭病。初始值必須是常量表達(dá)式。
class Account {
private:
static constexpr int period = 30;
}
拷貝控制
class Foo {
public:
Foo();
Foo(const Foo&); // 拷貝構(gòu)造函數(shù)
}
[1] C++ primer 中文版 第五版筆記