Мне нужен конструктор по умолчанию без аргументов. Как я могу инициализировать атрибут a
который неизвестного мне типа.
template <typename Type>
class Foo
{
public:
Foo() : a(), b(0) {} <---- Here is the confusion
private:
Type a;
int b;
};
редактировать Ответ был дан в комментариях ниже, но есть еще кое-что, что я не понимаю. Если у меня есть :
typedef enum {AB, CD} EnumType
template <typename Type>
class Foo
{
public:
Foo() {} // <---- "Member 'b' was no initialized in this constructor"
private:
Type a;
EnumType b;
};
мой компилятор дает мне это предупреждение: Member 'b' was no initialized in this constructor
, Почему это дает мне это предупреждение для b
который является перечислением, а не для a
?
это правильно, пока тип Type
имеет конструктор по умолчанию. когда вы объявляете шаблон, вы предполагаете некоторые вещи о типах, не каждый тип может быть передан в конструктор определенного шаблона.
здесь все будет хорошо для стандартных типов и для тех, у которых есть конструктор по умолчанию. если вы инициализируете класс Foo
с вашим собственным типом, который не предоставляет конструктор по умолчанию, это будет ошибкой.
чтобы ответить на ваш второй вопрос:
Если бы вы определили свою переменную в области имен, она будет иметь значение, равное 0.
enum SomeEnum {
EValue1 = 1,
EValue2 = 4,
};
SomeEnum e; // e is 0
int i; // i is 0
int main()
{
cout << e << " " << i; //prints 0 0
}
Не удивляйся что e
может иметь значения, отличные от любого из SomeEnum
Перечислим значения. Каждый тип перечисления имеет базовый целочисленный тип (такой как int
, short
, или же long
) и набор возможных значений объекта этого типа перечисления является набором значений, которые имеет базовый целочисленный тип. Enum — это просто способ удобно назвать некоторые значения и создать новый тип, но вы не ограничиваете значения вашего перечисления набором значений перечислителей.
Инициализация нуля объекта типа T означает:
— если T скалярного типа (3.9), объекту присваивается значение 0
(ноль) преобразуется в T;
Обратите внимание, что перечисления являются скалярными типами.
Инициализировать значение объекта типа T означает:
— если T является типом класса
бла бла
— если T не является объединенным классом
типа бла бла
— если T является типом массива, то бла-бла —
в противном случае объект инициализируется нулями
typedef enum {a,b,c,d} EnumType;
template <typename Type>
class Foo
{
public:
Foo() {} // <---- "Member 'b' was no initialized in this constructor"
public:
Type a;
EnumType b;
};
/*
*
*/
int main(int argc, char** argv) {
Foo<int> fo;
std::cout<<std::endl<<"fo.a:"<<fo.a<<",fo.b:"<<fo.b<<std::endl;
EnumType e=d;
fo.b=d;
std::cout<<std::endl<<"fo.a:"<<fo.a<<",fo.b:"<<fo.b<<std::endl;
Foo<int>* go=new Foo<int>;
std::cout<<std::endl<<"go->a:"<<go->a<<",go->b:"<<go->b<<std::endl;
go->b=d;
std::cout<<std::endl<<"go->a:"<<go->a<<",go->b:"<<go->b<<std::endl;
fo.a: -137090040, fo.b: 32767
fo.a: -137090040, fo.b: 3
Перейти-> а: -166889576, Перейти-> б: 32767
Перейти-> а: -166889576, Перейти-> б: 3
сейчас:
Foo<int>* go=new Foo<int>();
std::cout<<std::endl<<"go->a:"<<go->a<<",go->b:"<<go->b<<std::endl;
go->b=d;
std::cout<<std::endl<<"go->a:"<<go->a<<",go->b:"<<go->b<<std::endl;
Перейти-> а: 0, Перейти-> Ь: 0
Перейти-> а: 0, Перейти-> б: 3
Как я могу инициализировать атрибут а неизвестного мне типа.
Ваше решение правильное. Согласно пункту 8.5 / 11 стандарта C ++ 11:
Объект, инициализатором которого является пустой набор скобок, то есть (), должен быть инициализирован значением. […]
Затем пункт 8.5 / 8:
Инициализировать значение объекта типа T означает:
— если T является (возможно, cv-квалифицированным) типом класса (раздел 9) без конструктора по умолчанию (12.1) или
конструктор по умолчанию, который предоставляется или удаляется пользователем, затем объект инициализируется по умолчанию;— если T является (возможно, cv-квалифицированным) типом класса, не являющимся объединением, без предоставленного пользователем или удаленного конструктора по умолчанию,
тогда объект инициализируется нулями и, если T имеет нетривиальный конструктор по умолчанию, инициализируется по умолчанию;— если T является типом массива, то каждый элемент инициализируется значением;
— иначе объект инициализируется нулями.
В заключение,
Почему он дает мне это предупреждение для b, который является перечислением, а не для a?
Это, вероятно, потому что вы указываете аргумент шаблона для Type
который является UDT (определяемый пользователем тип), который может быть построен по умолчанию. Если это не так, то я ожидаю, что компилятор также предупредит вас о a
не инициализируется в конструкторе. Обратите внимание, однако, что компилятор не требуется выдать любое такое предупреждение.