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

时间:2011-12-20 17:50:39

标签: c++ arrays constructor

我正在尝试使用自定义类声明一个数组。当我向类中添加构造函数时,我的编译器抱怨“没有用于初始化name [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;
}

我可以做些什么来实现这个目标?我做错了什么?

6 个答案:

答案 0 :(得分:22)

您必须提供默认构造函数。当你在这里时,也要修复你的其他构造函数:

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

答案 1 :(得分:5)

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

您的选择:

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

      name someName[4] = { { "Arthur", "Dent" },
                           { "Ford", "Prefect" },
                           { "Tricia", "McMillan" },
                           { "Zaphod", "Beeblebrox" }
                         };
    
  • 改为使用std::vector,只有在构建元素时才添加元素。

答案 2 :(得分:2)

您需要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"} };

答案 3 :(得分:2)

你只需要在你的类中添加一个默认构造函数,如下所示:

class name {
  public:
    string first;
    string last;

  name() {
  }

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

答案 4 :(得分:2)

你的班级:

class name {
  public:
    string first;
    string last;

  name() { }  //Default constructor.

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

有一个显式构造函数,需要两个字符串参数。没有明确编写构造函数的类获取不带参数的默认构造函数。添加显式命令会阻止编译器为您生成默认构造函数。

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

答案 5 :(得分:2)

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

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

- 写一个空构造函数:

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

`