C++知識點隨筆(三):static、const、friend、inline

一、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

發佈了27 篇原創文章 · 獲贊 3 · 訪問量 1萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章