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

#c #inheritance #constructor #default-constructor #unnamed-class

#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::stringamp; 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" };
  

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