Инициализация члена в перегруженном конструкторе

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

В константах.hpp

#pragma once
enum class OpenglESVersion{
    OES1,
    OES2
};

В Cone.hpp у меня есть член enum

OpenglESVersion esVersion;

Определение перегруженного конструктора в Cone.cpp, которое принимает перечисление в качестве параметра.

Cone::Cone(const OpenglESVersion version) : rotationAngle(0), scale(1), esVersion(version) {}

Теперь в My RenderingEngine.cpp, когда я создаю экземпляр объекта Cone:

Cone cone(OpenglESVersion::OES2);

Я получаю синтаксическую ошибку:

Нет типа с именем «OES2» в «OpenglESVersion».

Теперь, если я обновлю экземпляр своего объекта до:

Cone cone{OpenglESVersion::OES2};

Теперь это работает.

Мой компилятор — libc++ [стандартная библиотека LLVM c++ с поддержкой c++ 11], а диалект — c++11[-std=c++11]. Я использую XCode.

Теперь, что касается моих сомнений: я просмотрел ресурсы, чтобы прояснить концепцию. В прошлом я использовал версию до С++ 11 в школе после книги Бьярна по программированию на С++, которая была напечатана в 2008 году, поэтому я не нашел этот «кудрявый» синтаксис инициализации в книге для С++ 11, вышедшей позже.

Я попробовал Google и не был уверен, какое ключевое слово искать, но позже наиболее распространенное имя темы указывало на «инициализацию списка». Почти каждый ресурс освещал преимущества этого нового синтаксиса в С++ 11, но мне так и не объяснили, почему обычная круглая скобка рассматривается как синтаксическая ошибка, потому что существует много ресурсов, где пример показывает использование круглой скобки с комбинацией фигурных скобок. объясняя разницу, но они использовали примеры примитивных типов, таких как:

int x(4);
int x{4};

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

  • Мой компилятор сделал этот синтаксис инициализации круглых скобок устаревшим?
  • Это не устарело, но никогда не поддерживалось в С++?
  • Я неправильно объявил и определил перегруженный конструктор?
  • Не поддерживается ли инициализация члена с помощью синтаксиса круглых скобок? и почему?

РЕДАКТИРОВАТЬ: это происходит для любой перегруженной версии, скажем, перегруженной версии конструктора с параметром int.

Cone::Cone(const int fooVariable) : fooMember(fooVariable){}

Работает только код:

Cone cone{8};

я получил

Декларатор ожидаемого параметра, Expected ')'

для Cone cone(8);

Этого поведения не происходит, если из любопытства я создаю экземпляр внутри функции-члена самого класса Cone, как будто компилятор не выдает никакого синтаксиса или какой-либо ошибки:

void Cone::Test(){
    Cone cone(OpenglESVersion::OES2);
}

РЕДАКТИРОВАТЬ ОБНОВЛЕНИЕ 2: я думаю, что у меня есть еще один тестовый пример, который определенно должен сузиться. Итак, вот шаблон:

class RenderingEngine
{
private:
    Cone cone(OpenglESVersion::OES2);
};

Итак, я объявляю и создаю объект Cone как член класса RenderingEngine. Так может ли это быть причиной моей проблемы? Потому что если я сделаю

Cone cone(OpenglESVersion::OES2);

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


person padam thapa    schedule 11.09.2017    source источник
comment
Это похоже на самый неприятный разбор.   -  person    schedule 11.09.2017
comment
Не удается воспроизвести   -  person Passer By    schedule 11.09.2017
comment
@PasserBy Привет, синтаксис Cone con(OpenglESVersion::OES2); Я попытался вызвать функцию-член в том же классе/файле Cone и работает, что означает, что компилятор не выдает никаких ошибок. Мне было любопытно это проверить. Но если экземпляр создан из другого класса и файла, как в моем вопросе, то это происходит. Можешь попробовать?   -  person padam thapa    schedule 11.09.2017
comment
Я предполагаю, что OpenglESVersion уже определено в opengl, а у меня не установлен opengl и я не могу его протестировать   -  person Passer By    schedule 11.09.2017
comment
Это настраиваемое перечисление, не встроенное. Я переименовал enum в FOO. Та же ошибка. И это не только для enum. Это происходит для любой перегруженной версии, скажем, перегруженной версии конструктора с параметром int.   -  person padam thapa    schedule 11.09.2017
comment
Я отредактировал свой вопрос, указав больше тестов, чтобы сузить проблему.   -  person padam thapa    schedule 11.09.2017
comment
Не могли бы вы сделать минимальный воспроизводимый пример? Я не могу добиться такого же поведения. И вы, вероятно, могли бы исправить это, делая это.   -  person f1u77y    schedule 11.09.2017
comment
@ f1u77y Привет, я обновил вопрос и сузил его, чтобы воспроизвести шаблон. Спасибо.   -  person padam thapa    schedule 11.09.2017


Ответы (1)


Инициализация члена была введена в C++11.

Скобки не поддерживаются, чтобы избежать самого неприятного синтаксического анализа, поэтому вы можете использовать синтаксис {..} или =:

class RenderingEngine
{
private:
    Cone cone{OpenglESVersion::OES2};
};

or

class RenderingEngine
{
private:
    Cone cone = Cone(OpenglESVersion::OES2); // With =, you can use parent on right side
};
person Jarod42    schedule 11.09.2017
comment
Привет. Спасибо. Как в моем примере инициализация члена может стать неоднозначной? - person padam thapa; 11.09.2017
comment
Как-то так: Cone cone(Cone()); - person Jarod42; 11.09.2017