Единая инициализация внутри списка параметров объявления конструктора / функции - PullRequest
0 голосов
/ 14 октября 2018

Я изучаю некоторые базовые вещи о классах и ООП в 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используя равномерную инициализацию , но не нормально инициализировать x , как в качестве аргумента по умолчанию в заголовке функции (я использую gcc6.3 с -std = c ++ 17).Почему это?Извиняюсь, если я до сих пор не понял помощи.

#include <iostream>

void printNum(int x {1}) //error
{
    std::cout<<x<<"\n";
}

int main()
{
    int n {5};  //OK

    printNum(n);
}

1 Ответ

0 голосов
/ 15 октября 2018

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

parameter-declaration-clause:
  parameter-declaration-list<sub>opt</sub> ...<sub>opt</sub>
  parameter-declaration-list , ...

parameter-declaration-list:   
  parameter-declaration
  parameter-declaration-list , parameter-declaration

parameter-declaration:    
  attribute-specifier-seq<sub>opt</sub> decl-specifier-seq declarator 
  attribute-specifier-seq<sub>opt</sub> decl-specifier-seq declarator = initializer-clause
  attribute-specifier-seq<sub>opt</sub> decl-specifier-seq abstract-declarator<sub>opt</sub>
  attribute-specifier-seq<sub>opt</sub> decl-specifier-seq abstract-declarator<sub>opt</sub> = initializer-clause

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

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

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

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

...