如何使用自定义类声明数组?

时间:2021-07-17 20:54:08

I'm trying to declare an array with a custom class. When I added a constructor to the class, my compiler complains that there's "No matching constructor for initialization of name[3]".

我试图声明一个带有自定义类的数组。当我向类添加构造函数时,我的编译器会抱怨“没有匹配的构造函数来初始化名称[3]”。

Here's my program:

这是我的计划:

#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;
}

What can I do to make this run, and what am I doing wrong?

我能做些什么来让它运行,我做错了什么?

6 个解决方案

#1


17  

You have to provide a default constructor. While you're at it, fix your other constructor, too:

您必须提供一个默认的构造函数。当你在做的时候,也修复你的另一个构造函数:

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

Alternatively, you have to provide the initializers:

或者,您必须提供初始化器:

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

The latter is conceptually preferable, because there's no reason that your class should have a notion of a "default" state. In that case, you simply have to provide an appropriate initializer for every element of the array.

后者在概念上更可取,因为没有理由认为您的类应该具有“默认”状态的概念。在这种情况下,您只需为数组的每个元素提供一个适当的初始化器。

Objects in C++ can never be in an ill-defined state; if you think about this, everything should become very clear.

c++中的对象永远不会处于定义不明确的状态;如果你仔细想想,一切都会变得非常清晰。


An alternative is to use a dynamic container, though this is different from what you asked for:

另一种选择是使用动态容器,尽管这与您要求的不同:

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

#2


5  

To default-initialize an array of Ts, T must be default constructible. Normally the compiler gives you a default constructor for free. However, since you declared a constructor yourself, the compiler does not generate a default constructor.

要默认初始化Ts数组,T必须是默认可构造的。通常编译器会免费为您提供一个默认构造函数。但是,由于您自己声明了构造函数,所以编译器不会生成默认构造函数。

Your options:

你的选择:

  • add a default constructor to name, if that makes sense (I don't think so, but I don't know the problem domain);
  • 添加一个默认构造函数来命名,如果这有意义(我不这么认为,但是我不知道问题域);
  • initialize all the elements of the array upon declaration (you can do this because name is an aggregate);

    在声明时初始化数组的所有元素(您可以这样做,因为名称是一个聚合);

      name someName[4] = { { "Arthur", "Dent" },
                           { "Ford", "Prefect" },
                           { "Tricia", "McMillan" },
                           { "Zaphod", "Beeblebrox" }
                         };
    
  • use a std::vector instead, and only add element when you have them constructed.

    使用std::vector,只在构造元素时添加元素。

#3


2  

you just need to add a default constructor to your class to look like this:

您只需向类中添加一个默认构造函数,使其看起来如下所示:

class name {
  public:
    string first;
    string last;

  name() {
  }

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

#4


2  

Your class:

你的类:

class name {
  public:
    string first;
    string last;

  name() { }  //Default constructor.

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

Has an explicit constructor that requires two string parameters. Classes with no constructor written explicitly get default constructors taking no parameters. Adding the explicit one stopped the compiler from generating that default constructor for you.

具有需要两个字符串参数的显式构造函数。没有显式写入构造函数的类获得默认构造函数,不包含参数。添加显式构造函数可以阻止编译器为您生成默认构造函数。

So, if you wish to make an array of uninitialized objects, add a default constructor to your class so the compiler knows how to create them without providing those two string parameters - see the commented line above.

因此,如果您希望创建一个未初始化对象的数组,请向您的类添加一个默认构造函数,以便编译器知道如何在不提供这两个字符串参数的情况下创建它们——请参阅上面的注释行。

#5


2  

You need a parameterless constructor to be able to create an instance of your class. Your current constructor requires two input string parameters.

需要一个无参数的构造函数才能创建类的实例。当前构造函数需要两个输入字符串参数。

Normally C++ implies having such a constructor (=default parameterless constructor) if there is no other constructor declared. By declaring your first constructor with two parameters you overwrite this default behaviour and now you have to declare this constructor explicitly.

通常,如果没有声明其他构造函数,c++意味着拥有这样的构造函数(=默认的无参数构造函数)。通过使用两个参数声明您的第一个构造函数,您将改写此默认行为,现在您必须显式声明此构造函数。

Here is the working code:

以下是工作代码:

#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; 
}

(BTW, you need to include to make the code compilable.)

(顺便说一句,您需要包含使代码可编译的内容。)

An alternative way is to initialize your instances explicitly on declaration

另一种方法是在声明中显式初始化实例

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

#6


2  

In order to create an array of objects, the objects need a constructor that doesn't take any paramters (that creates a default form of the object, eg. with both strings empty). This is what the error message means. The compiler automatically generates a constructor which creates an empty object unless there are any other constructors.

为了创建对象数组,对象需要一个不带任何参数的构造函数(它创建对象的默认形式,例如。与字符串是空的)。这就是错误消息的含义。编译器自动生成一个构造函数,该构造函数创建一个空对象,除非有其他构造函数。

If it makes sense for the array elements to be created empty (in which case the members acquire their default values, in this case, empty strings), you should:

如果将数组元素创建为空(在这种情况下,成员获取其默认值,在这种情况下,为空字符串),您应该:

-Write an empty constructor:

写一个空的构造函数:

class name {
  public:
    string first;
    string last;

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

-Or, if you don't need it, remove the existing constructor.

或者,如果不需要,删除现有的构造函数。

If an "empty" version of your class makes no sense, there is no good solution to provide initialisation paramters to all the elements of the array at compile time. You can:

如果类的“空”版本没有任何意义,那么就没有好的解决方案在编译时为数组的所有元素提供初始化参数。您可以:

  • Have a constructor create an empty version of the class anyway, and an init() function which does the real initialisation
  • 无论如何,构造函数要创建类的空版本,而init()函数要进行真正的初始化
  • Use a vector, and on initialisation create the objects and insert them into the vector, either using vector::insert or a loop, and trust that not doing it at compile time doesn't matter.
  • 使用一个向量,在初始化时创建对象并将它们插入到向量中,可以使用vector::insert或循环,并且相信在编译时不这样做并不重要。
  • If the object can't be copied either, you can use an array/vector of smart pointers to the object and allocate them on initialisation.
  • 如果该对象不能被复制,您可以使用一个智能指针的数组/矢量,并将它们分配给初始化。
  • If you can use C++11 I think (?) you can use initialiser lists to initialise a vector and intialise it (I'm not sure if that works with any contructor or only if the object is created from a single value of another type). Eg: .
  • 如果您可以使用c++ 11,我想(?)您可以使用initialiser列表来初始化一个向量,并将其初始化(我不确定这是否与任何contructor兼容,或者仅当对象是由另一个类型的单个值创建的)。如:。
 std::vector<std::string> v = { "xyzzy", "plugh", "abracadabra" };

`

#1


17  

You have to provide a default constructor. While you're at it, fix your other constructor, too:

您必须提供一个默认的构造函数。当你在做的时候,也修复你的另一个构造函数:

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

Alternatively, you have to provide the initializers:

或者,您必须提供初始化器:

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

The latter is conceptually preferable, because there's no reason that your class should have a notion of a "default" state. In that case, you simply have to provide an appropriate initializer for every element of the array.

后者在概念上更可取,因为没有理由认为您的类应该具有“默认”状态的概念。在这种情况下,您只需为数组的每个元素提供一个适当的初始化器。

Objects in C++ can never be in an ill-defined state; if you think about this, everything should become very clear.

c++中的对象永远不会处于定义不明确的状态;如果你仔细想想,一切都会变得非常清晰。


An alternative is to use a dynamic container, though this is different from what you asked for:

另一种选择是使用动态容器,尽管这与您要求的不同:

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

#2


5  

To default-initialize an array of Ts, T must be default constructible. Normally the compiler gives you a default constructor for free. However, since you declared a constructor yourself, the compiler does not generate a default constructor.

要默认初始化Ts数组,T必须是默认可构造的。通常编译器会免费为您提供一个默认构造函数。但是,由于您自己声明了构造函数,所以编译器不会生成默认构造函数。

Your options:

你的选择:

  • add a default constructor to name, if that makes sense (I don't think so, but I don't know the problem domain);
  • 添加一个默认构造函数来命名,如果这有意义(我不这么认为,但是我不知道问题域);
  • initialize all the elements of the array upon declaration (you can do this because name is an aggregate);

    在声明时初始化数组的所有元素(您可以这样做,因为名称是一个聚合);

      name someName[4] = { { "Arthur", "Dent" },
                           { "Ford", "Prefect" },
                           { "Tricia", "McMillan" },
                           { "Zaphod", "Beeblebrox" }
                         };
    
  • use a std::vector instead, and only add element when you have them constructed.

    使用std::vector,只在构造元素时添加元素。

#3


2  

you just need to add a default constructor to your class to look like this:

您只需向类中添加一个默认构造函数,使其看起来如下所示:

class name {
  public:
    string first;
    string last;

  name() {
  }

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

#4


2  

Your class:

你的类:

class name {
  public:
    string first;
    string last;

  name() { }  //Default constructor.

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

Has an explicit constructor that requires two string parameters. Classes with no constructor written explicitly get default constructors taking no parameters. Adding the explicit one stopped the compiler from generating that default constructor for you.

具有需要两个字符串参数的显式构造函数。没有显式写入构造函数的类获得默认构造函数,不包含参数。添加显式构造函数可以阻止编译器为您生成默认构造函数。

So, if you wish to make an array of uninitialized objects, add a default constructor to your class so the compiler knows how to create them without providing those two string parameters - see the commented line above.

因此,如果您希望创建一个未初始化对象的数组,请向您的类添加一个默认构造函数,以便编译器知道如何在不提供这两个字符串参数的情况下创建它们——请参阅上面的注释行。

#5


2  

You need a parameterless constructor to be able to create an instance of your class. Your current constructor requires two input string parameters.

需要一个无参数的构造函数才能创建类的实例。当前构造函数需要两个输入字符串参数。

Normally C++ implies having such a constructor (=default parameterless constructor) if there is no other constructor declared. By declaring your first constructor with two parameters you overwrite this default behaviour and now you have to declare this constructor explicitly.

通常,如果没有声明其他构造函数,c++意味着拥有这样的构造函数(=默认的无参数构造函数)。通过使用两个参数声明您的第一个构造函数,您将改写此默认行为,现在您必须显式声明此构造函数。

Here is the working code:

以下是工作代码:

#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; 
}

(BTW, you need to include to make the code compilable.)

(顺便说一句,您需要包含使代码可编译的内容。)

An alternative way is to initialize your instances explicitly on declaration

另一种方法是在声明中显式初始化实例

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

#6


2  

In order to create an array of objects, the objects need a constructor that doesn't take any paramters (that creates a default form of the object, eg. with both strings empty). This is what the error message means. The compiler automatically generates a constructor which creates an empty object unless there are any other constructors.

为了创建对象数组,对象需要一个不带任何参数的构造函数(它创建对象的默认形式,例如。与字符串是空的)。这就是错误消息的含义。编译器自动生成一个构造函数,该构造函数创建一个空对象,除非有其他构造函数。

If it makes sense for the array elements to be created empty (in which case the members acquire their default values, in this case, empty strings), you should:

如果将数组元素创建为空(在这种情况下,成员获取其默认值,在这种情况下,为空字符串),您应该:

-Write an empty constructor:

写一个空的构造函数:

class name {
  public:
    string first;
    string last;

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

-Or, if you don't need it, remove the existing constructor.

或者,如果不需要,删除现有的构造函数。

If an "empty" version of your class makes no sense, there is no good solution to provide initialisation paramters to all the elements of the array at compile time. You can:

如果类的“空”版本没有任何意义,那么就没有好的解决方案在编译时为数组的所有元素提供初始化参数。您可以:

  • Have a constructor create an empty version of the class anyway, and an init() function which does the real initialisation
  • 无论如何,构造函数要创建类的空版本,而init()函数要进行真正的初始化
  • Use a vector, and on initialisation create the objects and insert them into the vector, either using vector::insert or a loop, and trust that not doing it at compile time doesn't matter.
  • 使用一个向量,在初始化时创建对象并将它们插入到向量中,可以使用vector::insert或循环,并且相信在编译时不这样做并不重要。
  • If the object can't be copied either, you can use an array/vector of smart pointers to the object and allocate them on initialisation.
  • 如果该对象不能被复制,您可以使用一个智能指针的数组/矢量,并将它们分配给初始化。
  • If you can use C++11 I think (?) you can use initialiser lists to initialise a vector and intialise it (I'm not sure if that works with any contructor or only if the object is created from a single value of another type). Eg: .
  • 如果您可以使用c++ 11,我想(?)您可以使用initialiser列表来初始化一个向量,并将其初始化(我不确定这是否与任何contructor兼容,或者仅当对象是由另一个类型的单个值创建的)。如:。
 std::vector<std::string> v = { "xyzzy", "plugh", "abracadabra" };

`