c++基本語法:結構函數初始化列表。本站提示廣大學習愛好者:(c++基本語法:結構函數初始化列表)文章只能為提供參考,不一定能成為您想要的結果。以下是c++基本語法:結構函數初始化列表正文
C++為類中供給類成員的初始化列表
類對象的結構 次序是如許的:
1.分派內存,挪用結構函數 時,隱式/顯示的初始化各數據 成員
2.進入結構函數後在結構函數中履行普通盤算
應用初始化列表有兩個緣由:
1.必需如許做:
假如我們有一個類成員,它自己是一個類或許是一個構造,並且這個成員它只要一個帶參數的結構函數,而沒有默許結構函數,這時候要對這個類成員停止初始化,就必需挪用這個類成員的帶參數的結構函數,假如沒有初始化列表,那末他將沒法完成第一步,就會報錯。
class ABC
... {
public :
ABC( int x, int y, int z);
private :
int a;
int b;
int c;
} ;
class MyClass
... {
public :
MyClass():abc( 1 , 2 , 3 ) ... {}
private :
ABC abc;
} ;
由於ABC有了顯示的帶參數的結構函數,那末他是沒法依附編譯器生成無參結構函數的,所以沒有三個int型數據,就沒法創立ABC的對象。
ABC類對象是MyClass的成員,想要初始化這個對象abc,那就只能用成員初始化列表,沒有其他方法將參數傳遞給ABC類結構函數。
另外一種情形是如許的:當類成員中含有一個const對象時,或許是一個援用時,他們也必需要經由過程成員初始化列表停止初始化,由於這兩種對象要在聲明後立時初始化,而在結構函數中,做的是對他們的賦值,如許是不被許可的。
2.效力請求如許做:
類對象的結構次序顯示,進入結構函數體後,停止的是盤算,是對他們的賦值操作,明顯,賦值和初始化是分歧的,如許就表現出了效力差別,假如不消成員初始化類表,那末類對本身的類成員分離停止的是一次隱式的默許結構函數的挪用,和一次復制操作符的挪用,假如是類對象,如許做效力就得不到保證。
留意:結構函數須要初始化的數據成員,豈論能否顯示的湧現在結構函數的成員初始化列表中,都邑在該處完成初始化,而且初始化的次序和其在聲明時的次序是分歧的,與列表的前後次序有關 ,所以要特殊留意,包管二者次序分歧能力真正包管其效力。
為了解釋清晰,假定有如許一個類:
class foo{
private :
int a, b;
};
1、foo(){}和foo(int i = 0){}都被以為是默許結構函數,由於後者是默許參數。二者不克不及同時湧現。
2、結構函數列表的初始化方法不是依照列表的的次序,而是依照變量聲明的次序。好比foo外面,a在b之前,那末會先結構a再結構b。所以不管 foo():a(b + 1), b(2){}照樣foo():b(2),a(b+1){}都不會讓a獲得希冀的值。假如先聲明b再聲明a則會更好。
3、結構函數列表可以或許對const成員初始化。好比foo外面有一個int const c;則foo(int x) : c(x){}可讓c值賦成x。不外須要留意的是,c必需在每一個結構函數(假如有多個)都有值。
4、在繼續外面,只要初始化列表可以結構父類的private成員。好比說
class child : public foo{
}
foo外面的結構函數是如許寫的:foo (int x) { a = x; }.
而在child外面寫child(int x){ foo(x); }是經由過程不了編譯的。只要把父類初始化改成foo(int x) : a(x){}而子類結構寫作child (int x) : foo(x){}才可以。
C++ 初始化類的成員,不只可以用結構函數(constructor)完成,並且可以用初始化類成員列表來完成。MFC年夜量用到此辦法。例若有些初學者能夠不年夜懂得以下代碼:
class A
{
public:
int member_var; //成員變量
A(); //結構函數
}
A::A():member_var(0)
{
}
他們認為這個結構函數的界說應當只能如許寫:
A::A()
{
member_var=1;
}
其實兩種辦法都可。然則有些情形下,只能用第一種,並且平日情形下用第一種也會效力高些。
其實,第一種辦法是真實的初始化(initialization ),而在結構函數內完成的“=”操作實際上是賦值(assign)。這兩種辦法的一切差別從這兒開端。差別年夜概以下:
1.我們曉得通俗變量編譯器都邑默許的替你初始化。他們既能初始化,也能被賦值的,而常量(const)依照其意思只能被初始化,不克不及賦值。不然與變量就無差別了。所以常量成員(const member)只能用成員初始化列表來完成他們的“初始化”,而不克不及在結構函數內為他們“賦值”。
2.我們曉得類的對象的初始化其實就是挪用他的結構函數完成,假如沒有寫結構函數,編譯器會為你默許生成一個。假如你自界說了帶參數的結構函數,那末編譯器將不生成默許結構函數。如許這個類的對象的初始化必需有參數。假如如許的類的對象來做別的某個類的成員,那末為了初始化這個成員,你必需為這個類的對象的結構函數傳遞一個參數。異樣,假如你在包括它的這個類的結構函數裡用“=”,實際上是為這個對象“賦值”而非“初始化”它。所以一個類裡的一切結構函數都是有參數的,那末如許的類假如做為其余類的成員變量,你必需顯式的初始化它,你也是只能經由過程成員初始化列表來完成初始化。 例如:
class B
{
......
}
class A
{
public:
B member_b;
A();
}
A::A():B(...) //你必需顯式初始化它,由於他的一切結構函數
//都是有參數的,以後能力被賦值。
{
B=...; //由於如上所寫,曾經初始化了,能力被賦值,不然毛病。
}
初始化次序:
class test
{
const int a;
std:string str;
object o;
test():str(“df”),o(null) ,a(0)
{
}
};
黃色的既是初始化列表,他們會在結構函數正式挪用前被挪用,且他們的初始化次序其實不是依據 初始化列表中湧現的次序,而是他們聲明的次序來初始化。如上:
初始化次序是: a, str, o;
普通用於初始化 常量類型,靜態類型的數據,或許不克不及自力存在的數據