Как вызвать родительский конструктор не по умолчанию из безымянного производного класса в C++?

В C++ одноразовые структуры и классы могут быть объявлены безымянными, если объект создается напрямую:

struct { int x; int y; } point;

Безымянные классы также могут наследовать от базового класса. Это, например, полезно для создания списка различных "процессоров" из интерфейса базового процессора. Вот простой пример:

struct Processor {virtual int op(int a, int b) = 0;};
struct : Processor {int op(int a, int b) override { return a+b; }} Adder;
struct : Processor {int op(int a, int b) override { return a*b; }} Multiplier;

Итак, оба Adder а также Multiplier стать отдельными производными объектами Processorинтерфейс. Но что, если базовый процессор имеет большую структуру и конструктор, требующий параметров? Посмотрим на этот пример:

class Processor {
private:
    std::string name;
public:
    virtual int op(int a, int b) = 0;
    const std::string& getName() const { return name; }
    Processor(std::string name) : name(name) {}
};

Как создать безымянный подкласс для этого процессора, например "Сумматор". Наивная попытка:

class : public Processor {
public:
    int op(int a, int b) override { return a + b; }
} Adder { "Adder" };

к сожалению, не удается, потому что безымянный класс не имеет неявно сгенерированного конструктора, который принял бы "Adder"в качестве аргумента. И явно объявить такой конструктор также невозможно, потому что невозможно объявлять конструкторы в безымянных классах: конструктор называется так же, как и класс, но если нет имени класса, значит, нет и имени конструктора..

Я знаю, что есть простые обходные пути: один - все-таки дать имя (потенциально в пространстве имен), а затем использовать его для объявления конструктора. Также может возникнуть соблазн использовать виртуальныйinit() метод, который вызывается из конструктора Processor, и который выполняет работу, которую должен выполнять конструктор. Но это не работает, поскольку виртуальный вызов в конструкторе еще не достигает метода в производном классе. Но вместо этого призыв кinit() может быть скрыт в инициализаторе члена данных безымянного класса.

Но есть ли какой-нибудь "чистый" ответ C++, который оставляет безымянный класс безымянным и по-прежнему делает в конструкторе все, что должно быть сделано в конструкторе?

1 ответ

При написании этого вопроса я уже нашел ответ, поэтому поделюсь им здесь: в C++11 using ключевое слово было расширено, чтобы разрешить явный импорт конструкторов базового класса, и это аккуратно решает проблему:

class : public Processor {
using Processor::Processor;
public:
    int op(int a, int b) override { return a + b; }
} Adder { "Adder" };

Так Adder правильно создается при запуске программы, и пространство имен защищено от загрязнения.

Другие вопросы по тегам