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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/8579694/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-28 18:49:40  来源:igfitidea点击:

How do I declare an array with a custom class?

c++arraysconstructor

提问by Moshe

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?

我能做些什么来使这个运行,我做错了什么?

回答by Kerrek SB

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 shouldhave a notion of a "default" state. In that case, you simply haveto 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 dynamiccontainer, 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

回答by R. Martinho Fernandes

To default-initialize an array of Ts, Tmust 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 nameis an aggregate);

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

  • 为 name 添加一个默认构造函数,如果这有意义的话(我不这么认为,但我不知道问题域);
  • 在声明时初始化数组的所有元素(您可以这样做,因为它name是一个聚合);

      name someName[4] = { { "Arthur", "Dent" },
                           { "Ford", "Prefect" },
                           { "Tricia", "McMillan" },
                           { "Zaphod", "Beeblebrox" }
                         };
    
  • 使用 astd::vector代替,并且仅在构建元素时添加元素。

回答by Kamyar Souri

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

回答by John Humphreys - w00te

Your class:

你的班:

class name {
  public:
    string first;
    string last;

  name() { }  //Default constructor.

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

Has an explicitconstructor 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.

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

回答by Hyman V.

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 unlessthere 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
  • Use a vector, and on initialisation create the objects and insert them into the vector, either using vector::insertor a loop, and trust that not doing it at compile time doesn't matter.
  • 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: .
  • 无论如何,让构造函数创建一个空版本的类,以及一个init()进行真正初始化的函数
  • 使用 a vector,并在初始化时创建对象并将它们插入到 中vector,使用vector::insert或循环,并相信在编译时不这样做并不重要。
  • 如果对象也无法复制,则可以使用指向对象的智能指针数组/向量并在初始化时分配它们。
  • 如果您可以使用 C++11,我认为 (?) 您可以使用初始化列表来初始化一个向量并初始化它(我不确定这是否适用于任何构造函数,或者仅当对象是从另一个的单个值创建时类型)。例如:。
 std::vector<std::string> v = { "xyzzy", "plugh", "abracadabra" };
 std::vector<std::string> v = { "xyzzy", "plugh", "abracadabra" };

`

`

回答by Alexander Galkin

You need a parameterless constructorto 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 otherconstructor 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"} };