Это достаточно распространенная проблема, требующая гораздо более тщательного решения. Обратите внимание, что во всем этом коде я упростил инициализацию, удалив чтение переменных, чтобы сохранить небольшой размер кода. Представьте, что это все.
Один из подходов состоит в том, чтобы использовать функцию установки:
LudoPlayer play;
if (n == 3) {
play.set(1, 2, 3);
} else if (n == 4) {
play.set(1, 2, 3, 4);
}
Это работает, но требует, чтобы LudoPlayer
имела функцию set
, соответствующую каждому набору аргументов конструктора. Поэтому другой подход заключается в простом использовании конструктора:
LudoPlayer play;
if (n == 3) {
play = LudoPlayer(1, 2, 3);
} else if (n == 4) {
play = LudoPlayer(1, 2, 3, 4);
}
Эти два подхода известны как «двухфазное построение», и это обычно уничижительный термин. Конструктор должен перевести объект в работоспособное состояние, и вам не нужно немедленно go возвращать и переписывать это состояние.
Кроме того, для некоторых типов не имеет смысла иметь конструктор по умолчанию; каждый объект должен быть построен с некоторым внешним параметром, чтобы иметь смысл. Добавление бессмысленного конструктора по умолчанию для поддержки такого рода инициализации происходит изнутри дизайна.
Вместо этого вы можете выполнить соответствующую инициализацию при создании объекта:
LudoPlayer play = (n == 3) ? LudoPlayer(1, 2, 3) : LudoPlayer(1, 2, 3, 4);
Да, Я обманул: вы не можете сделать это, когда вам нужно запросить инициализаторы, как это сделал оригинальный код. Но это приводит к другому подходу: написать фабричную функцию.
LudoPlayer build(int n) {
if (n == 3) {
return LudoPlayer(1, 2, 3);
} else if (n == 4) {
return LudoPlayer(1, 2, 3, 4);
}
, когда вы создаете объект, просто вызовите фабричную функцию:
LudoPlayer play(build(n));
И, да, это требует, чтобы тип будучи построенным, имеет конструктор перемещения. Если вы траффируете c в не копируемых и неподвижных типах, у вас есть множество проблем помимо всего этого.
Что касается этой фабричной функции, то для чего-то такого простого это хорошо. Но если что-то происходит, легко потеряться. Я часто нахожу, что я редактирую не то место в этой if ... else if ...
лестнице. Поэтому напишите отдельные функции:
LudoPlayer build3() {
return LudoPlayer(1, 2, 3);
}
LudoPlayer build4() {
return LudoPlayer(1, 2, 3, 4);
}
LudoPlayer build(int n) {
if (n == 3) {
return build3();
} else if (n == 4) {
return build4();
}
}
Или напишите диспетчеру с оператором switch:
LudoPlayer build(int n) {
switch(n) {
case 3: return build3();
case 4: return build4();
}
}
В этом случае ваш компилятор может жаловаться на отсутствие оператора default
. Должен ли он быть, зависит от контекста. Если значение n
не было проверено, добавьте default
, который обрабатывает ошибку соответствующим образом. Если он уже был проверен, не добавляйте избыточный default
. Вы знаете свой код лучше, чем компилятор; отключи глупые предупреждения.