Переинициализировать с помощью делегирующего конструктора
У меня есть этот класс X
, используя делегирующий конструктор, я хочу изменить только значение i
а также j
как 0. Можно ли это сделать?
class X{
public:
X() = default;
X(int ival, int jval) : i{ ival }, j{ jval } {}
X(int new_i) : i{ new_i }, X(i, 0) {} //error here
private:
int i;
int j;
};
int main()
{
X x{ 345, 54 };
x = X{ 34 }; //annoymous copy changes only the i:member
return 0;
}
РЕДАКТИРОВАТЬ: я знаю X(int new_int) : X{new_int, 0}
будет работать, но я хотел знать, в чем ошибка, если инициализировать еще одну переменную в списке.
Может быть у меня есть другой z
и я хочу инициализировать это вместе с i
а также j
,
т.е. X(int new_i) :z{ new_i }, X(new_i, 0) {}
3 ответа
Просто используйте
X(int new_i) : X(new_i, 0) {}
Из проекта стандарта C++ N3337 (выделено мной):
12.6.2 Инициализация баз и членов
6 А
mem-initializer-list
может делегировать другому конструктору класса конструктора, используя любойclass-or-decltype
это обозначает сам класс конструктора. Еслиmem-initializer-id
обозначает класс конструктора, он должен быть единственнымmem-initializer
;
Почему бы тебе не сделать это?
X(int new_i) :X(new_i, 0){...}
Таким образом, вы будете устанавливать j
-го значения до 0, и имеют только x
переменная.
В списке инициализаторов не может быть делегирующего конструктора и другого инициализатора члена. Это недопустимо, поскольку порядок инициализации не может быть порядком объявления члена, вместо этого некоторые переменные будут инициализированы дважды, что потенциально плохо определено.
Если ваш пример был разрешен, то рассматриваемый конструктор сначала инициализируется i
<- new_i
, затем i
<- i
, затем j
<- 0
, С неconst
int
это может быть осуществимо, но не с более общими типами.
Просто инициализируйте объекты через делегирование:
class X
{
public:
X() = default;
X(int ival, int jval) : i{ival}, j{jval} {}
X(int ival) : X(ival, 0) {}
private:
int i;
int j;
};
Хотя в этом случае лучше использовать аргументы по умолчанию:
class X
{
public:
X() = default;
X(int ival, int jval=0) : i{ival}, j{jval} {}
private:
int i;
int j;
};
Вы также должны рассмотреть возможность использования explicit
ключевое слово для конструкторов с одним аргументом, чтобы избежать неприятных сюрпризов... как в
void foo(X);
foo(1); // calls foo(X(1));