2011-12-20 20 views
11

我想用自定義類聲明一個數組。當我向類中添加一個構造函數時,我的編譯器抱怨說「沒有匹配名稱初始化的構造函數[3]」。如何使用自定義類聲明數組?

這是我的計劃:

#include <iostream> 

using namespace std; 

class name { 
    public: 
    string first; 
    string last; 

    name(string a, string b){ 
    first = a; 
    last = b; 
    } 
}; 

int main (int argc, const char * argv[]) 
{ 

    const int howManyNames = 3; 

    name someName[howManyNames]; 

    return 0; 
} 

我能做些什麼,使這個跑,我究竟做錯了什麼?

回答

16

你必須提供一個默認的構造函數。當你在它,解決您的其它構造,太:

class Name 
{ 
public: 
    Name() { } 
    Name(string const & f, string const & l) : first(f), last(l) { } 
    //... 
}; 

或者,您必須提供初始化:

Name arr[3] { { "John", "Doe" }, { "Jane", "Smith" }, { "", "" } }; 

後者是概念上最好的,因爲沒有任何理由,你的類應該有一個「默認」狀態的概念。在這種情況下,您只需就可以爲提供適用於數組中每個元素的適當初始化程序。

C++中的對象永遠不會處於不明確的狀態;如果你想到這一點,一切都應該變得非常清楚。


另一種方法是使用動態容器,雖然這是你問什麼不同:

std::vector<Name> arr; 
arr.reserve(3); // morally "an uninitialized array", though it really isn't 

arr.emplace_back("John", "Doe"); 
arr.emplace_back("Jane", "Smith"); 
arr.emplace_back("", ""); 

std::vector<Name> brr { { "ab", "cd" }, { "de", "fg" } }; // yet another way 
+0

莢可以在不明確的狀態) – fredoverflow 2011-12-20 18:02:15

+1

@FredOverflow:他們不是 「不明確」 - 他們是 「未初始化」,這在概念上是明確定義的,其中的語義是你不能讀的。 – 2011-12-20 18:03:21

+0

好的,那麼會有什麼樣的東西可以*處於不明確的狀態? – fredoverflow 2011-12-20 18:10:39

3

您需要parameterless constructor才能創建您的班級實例。您當前的構造函數需要兩個輸入字符串參數。

如果有聲明沒有其他構造函數,通常C++意味着有這樣的構造函數(=默認無參數構造函數)。通過用兩個參數聲明第一個構造函數,可以覆蓋此默認行爲,現在必須明確聲明此構造函數。

這裏是工作的代碼:(順便說一句,你需要包括爲了使代碼編譯)

#include <iostream> 
#include <string> // <-- you need this if you want to use string type 

using namespace std; 

class name { 
    public: 
    string first; 
    string last; 

    name(string a, string b){ 
    first = a; 
    last = b; 

    } 

    name() // <-- this is your explicit parameterless constructor 
    {} 

}; 

int main (int argc, const char * argv[]) 
{ 

    const int howManyNames = 3; 

    name someName[howManyNames]; 

    return 0; 
} 

的另一種方法是初始化明確的聲明,您的情況

name someName[howManyNames] = { {"Ivan", "The Terrible"}, {"Catherine", "The Great"} }; 
4

爲默認初始化的T秒的陣列,T必須是缺省構造。通常,編譯器爲您提供一個免費的默認構造函數。但是,由於您自己聲明瞭構造函數,因此編譯器不會生成默認構造函數。

您的選擇:

  • 添加一個默認的構造函數來命名,如果是有道理的(我不這麼認爲,但我不知道問題域);
  • 聲明後初始化數組的所有元素(可以這樣做,因爲name是一個聚合);

    name someName[4] = { { "Arthur", "Dent" }, 
             { "Ford", "Prefect" }, 
             { "Tricia", "McMillan" }, 
             { "Zaphod", "Beeblebrox" } 
            }; 
    
  • 使用std::vector相反,只有當你讓他們構建添加元素。

1

你只需要一個默認的構造函數添加到您的類看起來像這樣:

class name { 
    public: 
    string first; 
    string last; 

    name() { 
    } 

    name(string a, string b){ 
    first = a; 
    last = b; 
    } 
}; 
1

你的類:

class name { 
    public: 
    string first; 
    string last; 

    name() { } //Default constructor. 

    name(string a, string b){ 
    first = a; 
    last = b; 
    } 
}; 

有一個明確構造函數需要兩個字符串參數。沒有構造函數的類明確地寫成不帶參數的默認構造函數。添加顯式的停止編譯器爲您生成該默認構造函數。

因此,如果您希望創建一個未初始化的對象數組,請在您的類中添加一個默認構造函數,以便編譯器知道如何在不提供這兩個字符串參數的情況下創建它們 - 請參閱上面的註釋行。

1

爲了創建一個對象數組,對象需要一個不帶任何參數的構造函數(創建該對象的默認形式,例如兩個字符串均爲空)。這是錯誤信息的含義。編譯器自動生成一個構造函數,該構造函數創建一個空對象,除非還有其他構造函數。

如果是有意義的,要創建空的數組元素(在這種情況下,成員獲得其默認值,在這種情況下,空字符串),你應該:

- 寫入一個空的構造:

class name { 
    public: 
    string first; 
    string last; 

    name() { } 
    name(string a, string b){ 
    first = a; 
    last = b; 
    } 
}; 

- 或者,如果你不需要它,刪除現有的構造函數。

如果類的「空」版本沒有意義,那麼在編譯時就沒有好的解決方案來爲數組的所有元素提供初始化參數。您可以:

  • 有一個構造反正創建該類的一個空的版本,以及init()函數做實際初始化
  • 使用vector,並在初始化創建對象並將其插入到vector,使用vector::insert或循環,並相信在編譯時不做它並不重要。
  • 如果無法複製對象,則可以使用智能指針的數組/向量指向對象並在初始化時分配它們。
  • 如果你可以使用C++ 11,我認爲(?)你可以使用初始化列表來初始化一個向量並初始化它(我不確定它是否適用於任何構造函數,或者只有當這個對象是從另一個類型的單個值創建的時候)。例如: 。
std::vector<std::string> v = { "xyzzy", "plugh", "abracadabra" }; 

`