一、static
靜態成員屬性爲什麼要在類外初始化?
靜態成員屬性之所以不能在構造函數內初始化,是因爲構造函數必須要在定義對象的時候纔會調用,而static變量在編譯的時候就創建了,所以要在類外通過類名作用域對static成員屬性初始化。
注意:sizeof()在C++中和C語言有不同,當我們:
cout << sizeof(//類名) << endl;
的時候,不是輸出這個類的大小,而是輸出定義一個這個類的對象需要申請多大的空間,所以如果這個類裏包含了靜態成員都不會計算在sizeof()內的,因爲靜態成員一個類只有一份兒,所以的對象共用他們。
struct Node
{
int age;
char c;
};
class CPeople
{
public:
int pp;
static const int qq = 100; //靜態常量整形數據成員才能在類內初始化
static Node node[2];
static int num; // 靜態成員一定要在類外初始化
public: //相當於全局變量,在編譯的時候就申請空間了,不用對象也能調用,(類名::)
CPeople()
{
pp = 100;
}
// 靜態成員函數:不能用普通的成員屬性,只能用 static 成員,因爲沒有this指針
static void Show()
{
//cout << this->pp << endl;
cout << num << endl;
cout << "static::show" << endl;
}
};
Node CPeople::node[2] = {{123,'d'},{456,'y'}}; //靜態結構體數組初始化
int CPeople::num = 123; //靜態成員的初始化
注意:靜態常量整形數據成員才能在類內初始化。所以short、long、char都可以,但是float、double不可以。
二、const
非靜態const成員屬性爲什麼一定要在初始化列表裏進行初始化?
在C中我們知道#define進行預定義的某個數是被分配內存的,其文件在編譯預處理過程中就會用定義好的數據去替代文中的符號。但是const卻是不一樣的,一般情況下編譯器也是不爲const創建空間的,只是將這個定義的數字保存在符號表中的。所以C++中const是在編譯的時候定義的,但是它的初始化可以在調用構造函數(也就是創建對象)的時候通過初始化列表的方式進行。調用構造函數的時候,首先是給該實例(類的具體對象)分配空間。使用初始化列表的話,就在分配空間的時候,同時將其空間初始化。但在構造函數的大括號裏,所有變(常)量的空間都已經分配好了,進行賦值操作。我們知道const是常量,只能進行初始化操作而不能進行賦值操作,所以必須在初始化列表中分配空間的同時進行初始化操作。
還有一個賦值次數,效率上的區別,初始化列表在對象初始化時對成員變量賦值一次,而使用構造函數內直接賦值的話,對成員變量賦值兩次,一次是對象構造是用默認值進行賦值,第二次是調用構造函數賦值。因爲普通成員變量是否初始化都可以,而且允許賦值操作,所以普通成員變量既可以使用初始化列表又可以使用構造函數賦值。
參考:http://blog.csdn.net/zhouyelihua/article/details/23252667
const成員函數
void Show(/*const CPeople* this*/) const // 常函數,不能修改類中的成員屬性
{
//this->a = 100; //錯誤,因爲 this 已經變成 const CPeople* this
}
常量類型的對象:
const CPeople pep;
只能調用常函數,普通函數用不了,因爲我們知道成員函數在使用的時候要把對象的地址傳進去,而我們用常量對象調用普通成員變量的時候,相當於:
void AA(/*CPeople* this = const CPeople* ll*/)
{
a = 567;
}
一定會報錯的。而const成員函數的this已經變了,所以常量對象可以調用const成員函數。反過來普通對象可以調用常函數。
三、friend
friend class BB; // 友元類
friend void Show(CPeople pp); // 友元函數,可以讓這個東西用自己的private成員
無論是友元類還是被友元類,都不能繼承這個友元關係。友元的友元也不能使用。友元就是只限定這一個可以用。
類的封裝性問題
友元函數是破壞類的封裝性的最大殺手。我們在使用成員函數返回類的私有成員屬性的時候也是很危險的,如果一定要使用的話,就將返回值設爲const。
四、inline
void AA() // 類內實現的都是內聯函數(默認的)
{
cout << "AA" << endl;
}
/*inline */void BB(); // 不是內聯的
inline void BB(); // 內聯的
不過編譯器自己也會有判斷,其實聲明爲inline只是對編譯器提出一個建議,建議編譯器進行內聯,而具體會不會內聯,由編譯器決定,編譯器會綜合考慮更方面因素來判斷要不要進行內聯。
內聯將函數代碼直接在調用的地方展開,而函數調用是一個跳轉語句,通過函數指針跳轉到函數體的地址,執行完再回來,所以inline是一種用空間換時間的方法。
參考我的另一篇博客:http://blog.csdn.net/u012300157/article/details/46763089