Единая инициализация внутри списка параметров объявления конструктора / функции

Я изучаю некоторые основные вещи о классах и ООП в 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);
}

3

Решение

Это грамматическое ограничение. Этот конкретный элемент грамматики описан в [dcl.fct] №3:

Параметр декларирование придаточного:
Параметр декларирование-листвыбирать ...выбирать
список объявлений параметров, ...

Параметр декларирование-лист:
Параметр декларирование
список объявлений параметров, объявление параметров

Параметр декларирование:
Атрибут спецификатор-слвыбирать декларатор decl-specier-seq
Атрибут спецификатор-слвыбирать decl-specier-seq декларатор = инициализатор-предложение
Атрибут спецификатор-слвыбирать decl-specier-seq абстрактный-деклараторвыбирать
Атрибут спецификатор-слвыбирать decl-specier-seq абстрактный-деклараторвыбирать = предложение-инициализатор

Стоит отметить, что грамматика позволяет присутствовать предложению инициализатора, только если ему предшествует =, Я подозреваю, что это гарантирует отсутствие двусмысленности между объявлениями функций и объявлений объектов. Например, в области блока:

Widget foo(CompA{}, CompB{});

Должно быть объявлением объекта, как хотелось бы убедиться в унифицированном предложении инициализации. Позволяя равнине {} в качестве аргумента по умолчанию вышеприведенный код будет неоднозначным, и у нас будет еще один неприятный синтаксический анализ для добавления в коллекцию. Так что = необходимо.

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

3

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

Других решений пока нет …

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