對于以下程式
#include <iostream>
using namespace std;
class university{
private:
string uni;
public:
university(){
cout<<"default constructor of university is invoked"<<endl;
}
university(string u){
uni =u;
cout<<"parametrized constructor of university is invoked: "<<uni;
}
};
class student{
private:
university u;
public:
student() {
u = university("ABC");
}
};
int main()
{
student s;
return 0;
}
輸出是:
default constructor of university is invoked
parametrized constructor of university is invoked: ABC
但是當更改學生類的建構式以使用初始化串列時,如下所示:
student(): u(university("ABC")){
}
輸出是:
parametrized constructor of university is invoked: ABC
我的問題是:
對于第二種情況,當編譯器university u在學生類的私有部分中運行該行時,它是創建類“大學”的物件“u”并為其分配記憶體地址,還是創建物件在初始化串列中?如果是前者,那為什么不呼叫默認建構式呢?
對于第一種情況,我有同樣的問題,物件是在哪里創建并分配記憶體位置的。
uj5u.com熱心網友回復:
“分配記憶體”和“分配記憶體位置”與這里無關。您正在詢問如何構造屬于另一個類的成員的物件。試圖在這里引入記憶體分配的主題只會使事情變得混亂。高級 C 技術允許在“同一個地方”重復構造和銷毀物件(通過放置新的和顯式的解構式呼叫)。實際的記憶體位置和物件構造/破壞完全無關緊要。它們之間沒有任何關系,如果您簡單地忘記有關記憶體位置的所有內容,只關注物件構造和銷毀的主題,這將很有幫助。說了這么多:
物件建構式負責構造物件的所有成員。這就是規則。沒有例外。句號。
student(): u(university("ABC")){
這會起作用,但這也會在一個令人困惑的成員中做到這一點。這說明了以下事件序列:構造一個臨時university物件,然后復制構造student該類的實際成員,最后該臨時物件被銷毀。這是不必要的,只會使水渾濁。使用更簡單的現代 C 語法,這應該是:
student(): u{"ABC"}{
這種更短、更直接的語法,以一種簡單明了的方式準確地描述了正在發生的事情:物件的建構式構造了該物件的所有成員,即這里只有一個。它被稱為u。u的建構式被呼叫,將字串作為引數傳遞給它。的university“引數化”建構式被呼叫。建構式的成員初始化部分只不過是一個簡單的串列:這是我的類成員,這里是它們各自建構式的引數。Abracadabra:它們是構建的。
student() {
如果建構式沒有成員初始化部分,或者沒有在初始化部分列出物件的成員,則呼叫相應的類成員的默認建構式。
就是這樣,這就是它的全部內容:您的類 *here the class is called student) 具有成員,并且該類的建構式顯式初始化它們,為類成員呼叫相應的建構式。如果任何類成員未在初始化部分列出,則呼叫其默認建構式,如果該類成員沒有默認建構式,則生成的代碼格式錯誤且無法編譯。
uj5u.com熱心網友回復:
成員未在建構式的主體中初始化。它們在建構式的主體執行之前被初始化。當你寫:
class student{
private:
university u;
public:
student() {
u = university("ABC");
}
};
然后u = unisversizy("ABC");不是初始化。由于您沒有為u成員提供初始化程式,它將通過呼叫其默認建構式來初始化。然后在建構式中university("ABC")通過呼叫另一個建構式創建另一個物件并將其分配給u.
PS:在我看來,術語“引數化建構式”是一個非常具有誤導性的術語。“引數化建構式”和教程中經常出現的默認建構式之間的區別是錯誤的。默認建構式是可以不帶引數呼叫的建構式,因此以下是默認建構式(并且可以帶引數呼叫):
struct foo {
foo(int x = 0) {} // a default constructor
// is this a parametrized constructor ?!?
};
uj5u.com熱心網友回復:
情況1
在這里,我們考慮以下情況:
student() {
u = university("ABC"); //this is assignment not initialization
}
當你寫道:
student s;
這些是上述陳述句的效果:
- 呼叫
student::student()類的默認建構式。student - 在進入/執行默認 ctor 的主體之前,會呼叫類
student::student()的默認 ctor 。結果,您將獲得以下輸出:university::university()university
default constructor of university is invoked
現在,一旦
university::university()完全執行了 ctor 的主體,student::student()就會恢復默認 ctor 的主體的執行。在執行
student::student()以下陳述句的主體時遇到:
u = university("ABC");
這是一個分配,而不是一個初始化。由于運算式,使用類的引數化建構式univerisity("ABC")創建了一個臨時university物件,因此您得到輸出:university
parametrized constructor of university is invoked: ABC
- 在最后一步中創建的臨時物件被分配給資料成員
u。
案例2
在這里,我們考慮以下情況:
student(): u(university("ABC")){
}
當你寫道:
student s;
這就是發生的事情:
student呼叫類的默認建構式。- Before entering the body of the default ctor
student::student(), the parameterized constructoruniversity::university(std::string)of classuniversityis called because you have the expressionuniversity("ABC")and the data memberuis initialized. Note that since the parameterized ctor was called you get the output:
default constructor of university is invoked
- Now when the body of the parameterized ctor is completed, execution of the body of default ctor
student::student()of classstudentresumes.
Note
In case 2 of your example, you should change student():u(university("ABC")){} to just:
student(): u("ABC"){
}
轉載請註明出處,本文鏈接:https://www.uj5u.com/qianduan/439877.html
