Конструктор по умолчанию в классе шаблона с атрибутом неизвестного типа

Мне нужен конструктор по умолчанию без аргументов. Как я могу инициализировать атрибут 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 ?

1

Решение

это правильно, пока тип 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

1

Другие решения

Как я могу инициализировать атрибут а неизвестного мне типа.

Ваше решение правильное. Согласно пункту 8.5 / 11 стандарта C ++ 11:

Объект, инициализатором которого является пустой набор скобок, то есть (), должен быть инициализирован значением. […]

Затем пункт 8.5 / 8:

Инициализировать значение объекта типа T означает:

— если T является (возможно, cv-квалифицированным) типом класса (раздел 9) без конструктора по умолчанию (12.1) или
конструктор по умолчанию, который предоставляется или удаляется пользователем, затем объект инициализируется по умолчанию;

— если T является (возможно, cv-квалифицированным) типом класса, не являющимся объединением, без предоставленного пользователем или удаленного конструктора по умолчанию,
тогда объект инициализируется нулями и, если T имеет нетривиальный конструктор по умолчанию, инициализируется по умолчанию;

— если T является типом массива, то каждый элемент инициализируется значением;

— иначе объект инициализируется нулями.

В заключение,

Почему он дает мне это предупреждение для b, который является перечислением, а не для a?

Это, вероятно, потому что вы указываете аргумент шаблона для Type который является UDT (определяемый пользователем тип), который может быть построен по умолчанию. Если это не так, то я ожидаю, что компилятор также предупредит вас о a не инициализируется в конструкторе. Обратите внимание, однако, что компилятор не требуется выдать любое такое предупреждение.

2

По вопросам рекламы [email protected]