1樓:匿名使用者
與類名稱具有一樣名稱的成員函式是建構函式。建構函式不能有返回值,甚至不能有return語句。說明一個有返回值的建構函式是錯誤的,取建構函式的地址也是錯誤的。
如果一個類有建構函式,在程式中每個該類型別的物件在使用之前由此建構函式進行初始化(有關初始化的更多資訊參見本章後面的「用特殊成員函式進行初始化」)。
建構函式是在物件的建立點上被呼叫的。建立物件可以是:
* 全域性物件(檔案範圍或外部連結的)。
* 在一個函式或者小的封閉塊中的區域性變數。
* 用new運算子建立的動態物件。new操作在程式的堆或自由儲存區中分配一個物件。
* 因顯式呼叫建構函式而建立的臨時物件(詳見本章後面的「臨時物件」)。
* 因編譯器隱含呼叫建構函式而建立的臨時物件(詳見本章後面的「臨時物件」)。
* 其它類的資料成員。在建立類型別的物件時,若此類型別由其它類型別變數組成,將會引起該類中每個物件的建立。
* 一個類的基類子物件。建立派生類型別的物件時會引起基類構件的建立。
建構函式的作用
一個建構函式執行各種任務,但對於程式設計師來說,這些任務是不可見的,你甚至可以不必為建構函式寫任何**。這些任務都同建立一個完全的、正確的類型別物件例項有關。
在ms c++中(同樣也在很多其它c++中)一個建構函式:
* 初始化物件的虛擬基指標(vbptr)。如果該類是由虛擬基類派生出的,則這一步要執行。
* 按說明的順序呼叫基類和成員的建構函式。
* 初始化物件的虛擬函式指標(vfptr)。如果該類有或者繼承了虛擬函式,則這一步要執行,虛擬函式指標指向類的虛擬函式表(v-table),並且使虛擬函式的呼叫同**正確繫結(binding)。
* 在建構函式體中執行可選的**。
當建構函式結束以後,所分配的儲存器就是一個給定類型別的物件。因為建構函式執行這些步驟,故虛擬函式的「遲後繫結」形態可以在虛擬函式的呼叫點得以解決,建構函式也要構造基類以及構造組合物件(作為資料成員的物件),遲後繫結是c++實現物件的多型行為的機制。
說明建構函式的規則
建構函式具有同類名相同的名稱。只要遵守過載函式的規則(有關詳情參見第12章「過載」),可以說明多個建構函式。
語法類名稱(參量說明表opt) cv-修飾符表opt
c++定義了兩種型別的建構函式,預設的和拷貝的建構函式。如表11.2所述。
表11.2 預設的和拷貝建構函式
建構函式的種類 參量 目的
預設建構函式 可以無參量呼叫 構造一個類型別的預設物件
拷貝建構函式 可以接受對同種類型別的引用作為唯一參量 拷貝類型別的物件
預設建構函式不要參量即可呼叫,但你可以說明一個帶有參量表的預設建構函式,只要讓所有的參量有預設值即可。同樣,拷貝建構函式必須接受同一類型別的引用作為唯一參量。但可以提供更多的參量,只要後續的參量具有預設值即可。
如果你不提供任何建構函式,編譯器會試圖生成一個預設的建構函式。同樣,如果你沒有提供拷貝建構函式,編譯器也會試圖產生一個。編譯器產生的建構函式視為公有的成員函式。
如果你說明一個拷貝建構函式,而其第一個參量是一個物件而不是一個引用,則會產生錯誤。
編譯器生成的預設建構函式建立物件(初始化vftables和vbtables,如前面所述),並呼叫基類及成員的預設建構函式,但不會採取其它的行動。基類和成員的建構函式只要存在,是可訪問的,並且是無二義性的就會被呼叫。
編譯器生成的拷貝建構函式建立一個物件,並且採用一個成員方式的拷貝來複制要被拷貝的物件的內容。如果基類或成員的建構函式存在,則它們將被呼叫,否則,就採取位方式的拷貝。
如果所有的基類和該類型別的成員類具有接受一個常量參量的建構函式,則編譯器生成的拷貝建構函式接受一個唯一的參量的型別是const type&;否則,編譯器生成的拷貝建構函式接受的唯一參量的型別是type &。
你可以用一個建構函式去初始化一個const和volatile物件,但建構函式本身不能說明為const和volatile的。對於建構函式唯一合法的儲存型別inline,對於建構函式使用任何其它的儲存類修飾符,包括__declspec關鍵字都會引起錯誤。建構函式和解構函式除了__stdcall外不能說明為其它的呼叫約定。
派生類是不能繼承基類中的建構函式的。當一個派生類的物件在建立的時候,它是從基類構件開始構造的,然而才進入派生類構件。編譯器使用每個基類的建構函式作為完整物件初始化的一部分(除了虛擬派生有所不同,參見本章後面的「初始化基類」)。
顯式地呼叫建構函式
在程式中,為建立給定型別的物件,可以顯式地呼叫建構函式。例如:建立兩個point型物件的描述一條線段的端點,可以寫如下**:
drawline(point(13,22),point(87,91);
建立了兩個point物件,傳遞給drawline函式,並在該表示式(函式呼叫)結束後拆除。
另外一個顯式地呼叫建構函式的情況是在一個初始化中:
point pt=point(7,11);
建立了一個point型別的物件,並用接受兩個整形參量的建構函式進行初始化。如前面的兩個例子中,通過顯式地呼叫建構函式建立的物件是無名的物件,並在它們所建立的表示式中是有生存期的。在本章後面的「臨時物件」中將對這一點進行深入的討論。
在建構函式內呼叫成員函式和虛擬函式
在建構函式裡面呼叫任何成員函式通常是很安全的,因為在執行第一行使用者**之前,物件已經完全建立起來了(已經初始化了虛表等等)。但是當成員函式呼叫了其抽象基類的虛擬成員函式時,在建構函式和解構函式呼叫此成員函式存在著潛在的不安全性。
建構函式可以呼叫虛擬函式。在呼叫虛擬函式時,被呼叫的是在建構函式自身的類中定義的函式(或者從其基類中繼承的函式)。下面的例子顯示了一個虛擬函式在一個建構函式中被呼叫時發生的情況。
#include
class base
;base::base()
void base::f()
class derived:public base
;derived::derived()
void derived::f()
void main()
在上面的程式執行的時候,derived d的說明會引發下列一系列事件:
1. 類derived的建構函式(derived::derived)被呼叫。
2. 在進入到derived類的構造體之前,基類base的建構函式被呼叫。
3. base::base呼叫函式f,它是一個虛擬函式。
通常被呼叫的函式會是derived::f,因為物件d是derived型別的物件。但因為base::
base是一個建構函式,此時的物件是一個derived型別的物件,故base::f將會被呼叫。
建構函式與陣列
陣列的構造只能使用預設的建構函式。預設建構函式要麼不接受任何參量,要麼對於它的所有參量都有預設的值。陣列通常是按升序來構造的,該陣列的每一個成員的初始化都是使用同一建構函式。
構造的次序
對於派生類或其成員資料是類型別的類,構造發生的順序有助於你理解,在任一給定的建構函式中你能夠使用物件的哪一部分。
構造與繼承
一個派生類的物件是從基類到派生類通過按次序為每個類呼叫建構函式來構造的。
每個類的建構函式能僅依賴於被完全構造好的它的基類。
有關初始化的完整描述,包括初始化的順序,見本章後面的「初始化基類及成員」。
構造與組合型別
含有類型別資料成員的類稱為組合類。當建立一個組合類型別的物件時,含有類的建構函式在該類的建構函式之前呼叫。 有關這種情況的初始化,見本章後面的「初始化基類及成員」。
2樓:浦旻騫
上面那個太多了,明顯是網上摘的,我的解釋是:建構函式就是與類名有相同名稱的成員函式,即:類名是a,該類中含有名字為a的成員函式,建構函式是可以過載的。
3樓:阿里山大王
對於構造方法的定義。一樓已經說得比較清楚了。關於過載問題,構造方法當然可以了,正如二樓所描述的。但你還要理解過載是怎樣構成的。
4樓:匿名使用者
樓上的牛人啊
建構函式就是 public 類名(引數列表)
它在你new 這個類的物件的時候被自動呼叫,就這麼簡單,一般用於給物件初始化的時候賦值或者讀取配置檔案備用
5樓:匿名使用者
給你的例子,你應該就能明白拉
public class test
test(string s)
public static void main (string main)}
c 建構函式過載,C 建構函式過載的問題?
應該是object 1 10 呼叫 sum int object 2 10.5 呼叫 sum double 因為c 在呼叫函式是會自動識別資料型別,如果你把10改為10.0,也是呼叫sum double 了 主要看你的引數是什麼型別的,如果是整型就呼叫sum int 浮點型的呼叫sum double...
在JAVA中,什麼是過載的建構函式
mxh快樂 建構函式的過載 舉個例子 public student public student string name public student string name,string age 上面三個函式都是student類的建構函式。第一個是無參的,第二個有一個引數,第三個有兩個引數。這就是...
如果過載建構函式this super如何使用
建構函式過載,引數個數不同,或者引數型別不同就可以了 this的話,簡單來說,你想呼叫當前類的方法或屬性的時候,就可以用 super,簡單的說,想呼叫父類的public或protected方法和屬性的時候,可以使用,這裡只能使用直接父類的,祖先類的呼叫不到。對於你的例子 class b b 引數1 ...