Вот ситуация:
У меня есть класс, определенный следующими файлами.
Файл Foo.h:
template<typename MyType>
class Foo
{
public:
Foo(int number = 50);
private:
typedef enum {VAR1, VAR2} Type;
class Bar
{
MyType a;
Type b;
Bar(int param1, Type param2) : a(param1), b(param2) {}
}
std::vector<Bar> vec;
};
Файл Foo.cpp:
template<typename MyType>
Foo::Foo(int number) : vec(number)
{ }
Проблема в том, что когда я компилирую это, я получаю сообщение об ошибке в первой строке файла .cpp, говорящее о том, что ему нужен конструктор для Bar без аргументов. Я думаю, что это нужно для создания вектора в Foo. Я добавил конструктор без аргументов для Bar, предоставив следующий файл .h:
template<typename MyType>
class Foo
{
public:
Foo(int number = 50);
private:
typedef enum {VAR1, VAR2} Type;
class Bar
{
MyType a;
Type b;
Bar() {} // <---- Line added
Bar(int param1, Type param2) : a(param1), b(param2) {}
}
std::vector<Bar> vec;
};
Теперь я могу скомпилировать, и это работает, но в строке, которую я только что добавил, есть предупреждение о том, что Member 'b' was no initialized in this constructor
, Может, проблема с enum?
Я не понимаю, что я должен сделать, чтобы заставить это работать без этого предупреждения.
редактировать : Я получил несколько ответов, в которых говорилось о добавлении списка инициализации в пустой конструктор. Тем не менее, мой класс на самом деле является шаблоном класса и a
это неизвестный тип для меня, поэтому я не могу инициализировать его, так как я не знаю его тип. Я пробовал только инициализировать b
в списке инициализации в баре, и это сработало. Предупреждение исчезло, но можно ли a
неинициализированный? Будет ли способ удалить конструктор без аргумента Bar и все же дать размер вектору в конструкторе Foo?
Проблема заключается в списке инициализатора в определении Foo::Foo(int)
, Ты пишешь
Foo::Foo(int n)
: vec(n) { }
то есть вы используете конструктор
std::vector<Bar>::vector(size_t number, const Bar &x = Bar())
Обратите внимание, что x = Bar()
это означает, что вы заполняете вектор стандартными построенными экземплярами Bar
, Так как есть по крайней мере один конструктор, определенный в Bar
компилятор не предоставляет автоматически стандартный конструктор.
Определите стандартный конструктор в Bar
как другие ответы предлагают или положить что-то еще в конструкторе Foo
например это
Foo::Foo(int n)
: vec(n, Bar(1, VAR1)) { }
и ошибка компилятора исчезает.
Ответ на ваше редактирование: Предупреждение, которое вы получаете, вероятно, означает: участник a
не правильно инициализирован. Так как это int
это может быть хорошо (C ++ не заставляет вас инициализировать int
с). Но остерегайтесь странных и произвольных значений в члене a
позже в вашей программе. Лучшее решение состоит в том, чтобы установить его во время создания в четко определенное состояние, что означает для вас «это значение неизвестно».
редактироватьЯ удалил все, что написал о гетерогенных контейнерах. Однако, если вам это нужно, взгляните на историю редактирования моего поста.
Вы можете инициализировать a
в стандартном конструкторе Bar
как это:
Bar::Bar() : a(MyType()), b(UNKNOWN) { }
и добавив UNKNOWN
к перечислению Type
, Это предполагает тип MyType
стандартно конструктивен Это относится, например, ко всем примитивным типам, таким как int
, double
и т. д. Это дает вам четко определенное состояние Bar
объект, который может значить для вас неизвестный. Это можно проверить, сравнив b
в UNKNOWN
,
Как сказал Якк в своем комментарии: Примитивные типы, такие как перечисления, можно оставить унифицированными, но в вашем случае компилятор предупреждает вас: это может быть ваш член b
содержит значение, которое не имеет метки, как VAR1
или же VAR2
совсем. Это всегда хорошая идея инициализировать все члены с четко определенными значениями, если вы действительно не обязаны этого делать — например, если выполнение является чертовски важным.
Вам нужно добавить список инициализации в пустой конструктор (и, возможно, сделать его общедоступным).
class Bar
{
int a;
Type b;
Bar() : a(0), b(VAR1) {} // initialize the members to default values.
Bar(int param1, Type param2) : a(param1), b(param2) {}
}