Обходной путь для унаследованного конструктора и дополнительных переменных

Мне нужен обходной путь или хорошее решение для инициализации группы постоянных переменных класса в базе и подклассе

Проблема проста, я получил базовый класс с двумя конструкторами и теми же двумя конструкторами в подклассе

class BASE {
int a;

int func(float x) { // just a dummy to show that this function
return (a = (int) x) + 2; // modifies a
}
public:
const int b;

BASE(const int b) : b(b) {} // doesn't use a
BASE(const float x) : a(0), b(func(x)) {}
};

struct SUB: public BASE {
const int c;
const int d;

SUB(const int b) : BASE(b), c(b), d(c + 3) {}
SUB(const float x) : BASE(x), c(b), d(c + 3) {}
};

Подкласс должен вызывать конструктор из BASE для инициализации переменных класса из BASE, после чего подкласс инициализирует остальные переменные

Пока все хорошо, но проблема в том, что оба конструктора из SUB делают одно и то же, за исключением вызова другого конструктора из BASE

Я хочу что-то подобное

    SUB() : c(b), d(c + 3) {} // BASE() needs to be defined
SUB(const int b) : BASE(b), SUB() {}
SUB(const float x) : BASE(x), SUB() {}

но это не работает, потому что «вызов делегирующего конструктора должен быть единственным инициализатором-членом» …

Перемещение всего за пределы списка инициализатора не работает, потому что это переменные класса const

2

Решение

Вы можете создать «конструктор пересылки» для вашего производного класса:

struct SUB: public BASE {
const int c;
const int d;

template <class... T>
SUB(T&&... a) : BASE(std::forward<T>(a)...), c(b), d(c + 3) {}
};

Это примет произвольные аргументы и направит их на BASE, Конечно, он будет компилироваться только при вызове с аргументами, которые действительны для BASE, но это верно для каждого случая.

Если вы хотите / должны быть супер-правильными, вы можете обусловить конструктор с помощью SFINAE на что-то вроде std::is_constructible<BASE, T&&...>, но я бы не стал беспокоиться.

2

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

К сожалению, это правила языка, если у вас есть делегирующий конструктор это должна быть единственная часть списка инициализатора.

Вам нужно обойти это ограничение, например, дублируя список инициализатора конструктора по умолчанию:

SUB(const int b) : BASE(b), c(b), d(c + 3) {}
2

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