Как заставить его вызвать правильный конструктор?


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

S s[5]; // calls default constructor five times, one for each S object

Но что, если мой класс не интерпретируется по умолчанию? Как я смогу создать экземпляр и впоследствии использовать этот массив?

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

S(int, int);

Как заставить его вызвать этот конструктор вместо конструктора по умолчанию?

3 5

3 ответа:

struct S
{
   const int m;
   S(int p, int k) : m(p) {}
};

S arr[4] = {S(1,1), S(1,2), S(1,3), S(1,4)};

Без copy-ctor вы все еще можете использовать следующую инициализацию списка C++11 - как Энди проул указывает, что ctor не может быть explicit для этого:

S arr[4] = {{1,1}, {1,2}, {1,3}, {1,4}};

Для более масштабируемого решения можно использовать либо std::array, либо std::vector:

std::array<S,4> make_array()
{
    // create array... and return
}

std::array<S,4> arr = make_array();

Используйте std::vector и заполните его объектами, которыевы решаете, как должны быть построены.

Например, в C++11 вы можете использовать функцию-член emplace_back(), чтобы написать что-то вроде этого:

#include <vector>

std::vector<S> v;
v.emplace_back(42, 1729);
v.emplace_back(0, 6);
// ...

Или даже:

std::vector<S> v = { {42, 1729}, {0, 6} };

, если конструктор S не помечен как explicit. Если это так, то вам придется написать:

std::vector<S> v = { S{42, 1729}, S{0, 6} }.

Еще в C++03, где emplace_back() и равномерной инициализации не существовало, вы могли бы сделать:

#include <vector>

std::vector<S> v;
v.push_back(S(42, 1729));
v.push_back(S(0, 6));
// ...

Но ваш класс должен быть копируемым для того, чтобы он компилировался.

В прошлом я делал некоторые:

S** s = new S*[5];

s[0] = new S(1, 2);
s[1] = new S(1, 2);

Просто чтобы иметь возможность вызывать другие конструкторы