1. 程式人生 > >C++11 FAQ中文版:類成員的內部初始化

C++11 FAQ中文版:類成員的內部初始化

1 Year 2011

類內部成員的初始化

在C++98標準裡,只有static const宣告的整型成員能在類內部初始化,並且初始化值必須是常量表達式。這些限制確保了初始化操作可以在編譯時期進行。例如:

    int var = 7;
    class X {
        static const int m1 = 7;   // 正確
        const int m2 = 7;    // 錯誤:無static
        static int m3 = 7;              // 錯誤:無const
        static const int m4 = var;  // 錯誤:初始化值不是常量表達式
        static const string m5 = “odd”; //錯誤:非整型
        // …
    };

C++11的基本思想是,允許非靜態(non-static)資料成員在其宣告處(在其所屬類內部)進行初始化。這樣,在執行過程中,需要初始值時建構函式可以使用這個初始值。考慮下面的程式碼:

    class A {
    public:
        int a = 7;
    };

這等同於:

    class A {
    public:
        int a;
        A() : a(7) {}
    };

從程式碼來看,這樣可以省去一些文字的輸入,但是真正受益的是擁有多個建構函式的類。在大多數情況下,所有的建構函式都會使用成員變數的常見初始值:

class A {
    public:
         A(): a(7), b(5), hash_algorithm(“MD5″), s(“Constructor run”) {}
        A(int a_val) :
          a(a_val), b(5), hash_algorithm(“MD5″),
          s(“Constructor run”)
          {}

        A(D d) : a(7), b(g(d)),
            hash_algorithm(“MD5″), s(“Constructor run”)
            {}
        int a, b;
    private:
        // 雜湊加密函式可應用於類A的所有例項
        HashingFunction hash_algorithm;
        std::string s;  // 指示的字串變數將持續整個物件的生命週期
    };

hash_algorithm和s每個都有一個單獨的預設值的事實會由於雜亂的程式碼而不明顯,這會在程式維護時造成麻煩。作為替代,可以將資料成員的初始值提取出來:

class A {
    public:
        A(): a(7), b(5) {}
        A(int a_val) : a(a_val), b(5) {}
        A(D d) : a(7), b(g(d)) {}
        int a, b;
    private:
        //雜湊加密函式可應用於類A的所有例項
        HashingFunction hash_algorithm{“MD5″};
        //指示的字串變數將持續整個物件的生命週期
        std::string s{“Constructor run”};
    };

如果一個成員同時在類內部初始化時和建構函式內被初始化,則只有建構函式的初始化有效(這個初始化值“優先於”預設值)(譯註:可以認為,類內部初始化先於建構函式初始化進行,如果是對同一個變數進行初始化,建構函式初始化會覆蓋類內部初始化)。因此,我們可以進一步簡化:

class A {
    public:
        A() {}
        A(int a_val) : a(a_val) {}
        A(D d) : b(g(d)) {}
        int a = 7;
        int b = 5;
    private:
        //雜湊加密函式可應用於類A的所有例項
        HashingFunction hash_algorithm{“MD5″};
        //指示的字串變數將持續整個物件的生命週期
        std::string s{“Constructor run”};
};

或參見:

  • the C++ draft section “one or two words all over the place”; see proposal.

自己試試:

X.h

class X

{

private:

int a = 5;

int b = 6;

};

main.cpp

#include "X.h"

int main()

{

X x;

return 0;

}

g++ -std=c++0x main.cpp

X.h:15:10: 對不起,尚未實現: non-static data member initializers
X.h:15:10: 錯誤: ISO C++ 不允許在類內初始化非常量靜態成員‘a’
X.h:16:10: 對不起,尚未實現: non-static data member initializers
X.h:16:10: 錯誤: ISO C++ 不允許在類內初始化非常量靜態成員‘b’

g++ --version
g++ (Ubuntu/Linaro 4.6.3-1ubuntu5) 4.6.3
Copyright © 2011 Free Software Foundation, Inc.