Я изучаю некоторые основные вещи о классах и ООП в C ++. Из того, что я прочитал, предпочтительный современный способ инициализации переменной заключается в использовании равномерной инициализации.
В приведенном ниже примере простого заголовка класса равномерная инициализация используется для инициализации 3 элементов данных (длина, ширина и высота).
Для согласованности я подумал, что было бы неплохо использовать равномерную инициализацию при установке значений по умолчанию в объявлении конструктора, но это не работает, и компилятор (gcc 6.3 в Debian Stretch) генерирует ошибку. Из того, что я вижу, компилятор считает, что фигурные скобки {} являются началом тела определения конструктора (очевидно, это не так, поскольку правая скобка «)» еще не добавлена).
Я согласен, что это не сработает, но из любопытства есть причина, почему? Я бы предпочел быть совместимым с моим кодом и использовать унифицированную инициализацию, где это возможно.
Благодарю.
#ifndef BOX_H
#define BOX_H
class Box
{
private:
double length {1.0};
double width {1.0};
double height {1.0};
public:
//constructor
Box(double l = 1.0, double w = 1.0, double h = 1.0); //ok
//Box(double l {1.0}, double w {1.0}, double h {1.0}); //Error
double volume();
};
#endif
РЕДАКТИРОВАТЬ …. спасибо за комментарии, но я не уверен, что понимаю причину, по которой вы не можете использовать одинаковую инициализацию для аргументов по умолчанию. Есть ли какая-то стандартная документация C ++, на которую кто-то может указать?
Например, взяв базовую программу ниже, можно инициализировать N со значением 5, используя равномерная инициализация но это не хорошо для инициализации Икс как это в качестве аргумента по умолчанию в заголовке функции (я использую gcc 6.3 с -std = c ++ 17). Почему это? Извиняюсь, если я до сих пор не понял помощи.
#include <iostream>
void printNum(int x {1}) //error
{
std::cout<<x<<"\n";
}
int main()
{
int n {5}; //OK
printNum(n);
}
Это грамматическое ограничение. Этот конкретный элемент грамматики описан в [dcl.fct] №3:
Параметр декларирование придаточного: Параметр декларирование-листвыбирать ...выбирать список объявлений параметров, ... Параметр декларирование-лист: Параметр декларирование список объявлений параметров, объявление параметров Параметр декларирование: Атрибут спецификатор-слвыбирать декларатор decl-specier-seq Атрибут спецификатор-слвыбирать decl-specier-seq декларатор = инициализатор-предложение Атрибут спецификатор-слвыбирать decl-specier-seq абстрактный-деклараторвыбирать Атрибут спецификатор-слвыбирать decl-specier-seq абстрактный-деклараторвыбирать = предложение-инициализатор
Стоит отметить, что грамматика позволяет присутствовать предложению инициализатора, только если ему предшествует =
, Я подозреваю, что это гарантирует отсутствие двусмысленности между объявлениями функций и объявлений объектов. Например, в области блока:
Widget foo(CompA{}, CompB{});
Должно быть объявлением объекта, как хотелось бы убедиться в унифицированном предложении инициализации. Позволяя равнине {}
в качестве аргумента по умолчанию вышеприведенный код будет неоднозначным, и у нас будет еще один неприятный синтаксический анализ для добавления в коллекцию. Так что =
необходимо.
Теперь, что касается того, почему бы не допустить это в конструкторе, где двусмысленность маловероятна: стандартный комитет на самом деле не имеет привычки разрешать очень ограниченный вариант использования, если более общий вариант не может поддерживаться.
Других решений пока нет …