Как объявить массив с пользовательским классом?

Я пытаюсь объявить массив с пользовательским классом. Когда я добавил конструктор в класс, мой компилятор жалуется, что там нет конструктора соответствия для инициализации имени [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;
}

Что я могу сделать, чтобы выполнить этот прогон, и что я делаю неправильно?

Ответ 1

Вы должны предоставить конструктор по умолчанию. Пока вы на нем, исправьте и другой конструктор:

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

В качестве альтернативы вы должны предоставить инициализаторы:

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

Последнее концептуально предпочтительнее, потому что нет причин, по которым ваш класс должен иметь представление о состоянии "по умолчанию". В этом случае вам просто нужно предоставить соответствующий инициализатор для каждого элемента массива.

Объекты на С++ никогда не могут находиться в некорректном состоянии; если вы думаете об этом, все должно стать очень ясным.


Альтернативой является использование динамического контейнера, хотя это отличается от того, что вы просили:

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

Для инициализации по умолчанию массива T s, T должен быть по умолчанию конструктивным. Обычно компилятор бесплатно предоставляет конструктор по умолчанию. Однако, поскольку вы сами объявили конструктор, компилятор не создает конструктор по умолчанию.

Ваши варианты:

  • добавить конструктор по умолчанию, если это имеет смысл (я так не думаю, но я не знаю проблемную область);
  • инициализировать все элементы массива после объявления (вы можете это сделать, потому что name является агрегатом);

      name someName[4] = { { "Arthur", "Dent" },
                           { "Ford", "Prefect" },
                           { "Tricia", "McMillan" },
                           { "Zaphod", "Beeblebrox" }
                         };
    
  • используйте std::vector вместо этого и добавьте только элемент, когда вы их построили.

Ответ 3

Для создания экземпляра вашего класса вам понадобится конструктор без параметров. Для вашего текущего конструктора требуются два параметра входной строки.

Обычно С++ подразумевает наличие такого конструктора (= конструктор без параметров без параметров), если объявлен конструктор другого. Объявив первый конструктор с двумя параметрами, вы переписываете это поведение по умолчанию, и теперь вы должны явно объявить этот конструктор.

Вот рабочий код:

#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

вам просто нужно добавить конструктор по умолчанию в свой класс, чтобы выглядеть так:

class name {
  public:
    string first;
    string last;

  name() {
  }

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

Ответ 5

Ваш класс:

class name {
  public:
    string first;
    string last;

  name() { }  //Default constructor.

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

Создает конструктор Явный, который требует двух параметров строки. Классы без конструктора, явно написанные, получают конструкторы по умолчанию, не требующие параметров. Добавление явного остановило компилятор от создания этого конструктора по умолчанию для вас.

Итак, если вы хотите создать массив неинициализированных объектов, добавьте конструктор по умолчанию в свой класс, чтобы компилятор знал, как их создавать, не предоставляя эти два строковых параметра - см. прокомментированную строку выше.

Ответ 6

Чтобы создать массив объектов, объектам нужен конструктор, который не принимает никаких параметров (что создает форму объекта по умолчанию, например, при обеим пустым пустым). Это означает сообщение об ошибке. Компилятор автоматически генерирует конструктор, который создает пустой объект, если нет других конструкторов.

Если смысл создания элементов массива пуст (в этом случае члены приобретают свои значения по умолчанию, в этом случае пустые строки), вы должны:

-Записать пустой конструктор:

class name {
  public:
    string first;
    string last;

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

-Or, если вам это не нужно, удалите существующий конструктор.

Если "пустая" версия вашего класса не имеет смысла, нет хорошего решения для предоставления параметров инициализации всем элементам массива во время компиляции. Вы можете:

  • Пусть конструктор создает пустую версию класса и функцию init(), которая выполняет реальную инициализацию
  • Используйте vector, а при инициализации создайте объекты и вставьте их в vector, либо используя vector::insert, либо цикл, и не верьте, что это не делается во время компиляции.
  • Если объект не может быть скопирован, вы можете использовать массив/вектор интеллектуальных указателей для объекта и выделить их при инициализации.
  • Если вы можете использовать С++ 11, я думаю, что (?) вы можете использовать списки инициализации для инициализации вектора и инициализировать его (я не уверен, что это работает с любым конструктором или только в том случае, если объект создается из одного значение другого типа). Например: .
 std::vector<std::string> v = { "xyzzy", "plugh", "abracadabra" };

`