Убедитесь, что во время компиляции все классы, производные от абстрактного базового класса, реализуют особую сигнатуру конструктора - PullRequest
0 голосов
/ 03 июля 2019

У меня есть абстрактный базовый класс и несколько объектов, которые могут наследоваться от него. Например

    class Mode {
        public:
        int n,l,m;
        double omega;
        virtual int doSomething() =0;
        virtual ~Mode(){};
    }

    class ModeA : Mode {
        ModeA(int N, int L, int M);
        ModeA(double W, int L, int M);
        virtual ~ModeA();
        int doSomething();
    }

    class ModeB : Mode {
        ModeB(int N, int L, int M);
        ModeB(double W, int l, int M);
        virtual ~ModeB();
        int doSomething();
    }    

Два дочерних класса ModeA и ModeB имеют конструкторы с параметрами (int, int, int) и (double, int, int). Позже у меня есть кусок кода, который ожидает как Mode объект, который выглядит как

    template <class MODE> int mode_finder(MODE** mode_list, int num_mode, int N, int L, int M){
        assert((std::is_base_of<Mode,MODE>::value));
        for(int i=0; i<num_mode; i++){
            mode_list[i] = new MODE(N,L,M);
             ... some more code here ...
        }
    }

(это не просто функция для инициализации списка режимов, часть ...some more code here... имеет длину около 300 строк и включает в себя проверку значений по списку, удаление и воссоздание, если они не совпадают - много материал был исключен из этого простого рабочего примера)

Если я использую ModeA и ModeB, то это нормально, потому что они имеют правильный вид конструкторов.

Моя проблема в том, что я (или тот, кто наследует этот код) может в конечном итоге создать новый тип и забыть вставить конструкторы этой формы, такие как

    class ModeC : Mode {
        ModeC(int X);
        virtual ~modeC();
        int doSomething();
    }

Это создаст ошибки времени выполнения, если я вызову mode_maker с ModeC, когда будет создан шаблон функции для ModeC.

Я хочу, чтобы каждый объект наследовал от Mode для реализации конструкторов с двумя сигнатурами: форма (int, int, int) и (double, int, int). Если нет, я хочу выдать ошибку во время компиляции.

Я предполагал, что чисто виртуальные конструкторы справятся, что-то вроде:

    virtual Mode(int, int, int) =0;
    virtual Mode(double, int, int) =0;

но очевидно, что это не языковая функция из-за проблем с vtable. Мне вообще не нужны записи в vtable, мне просто нужно, чтобы дочерние классы были вынуждены создавать конструкторы этого типа.

Как мне сделать то, что я пытаюсь сделать?

Заранее спасибо.

1 Ответ

0 голосов
/ 03 июля 2019

Это создаст ошибки времени выполнения, если я вызову mode_maker с ModeC, когда будет создан шаблон функции для ModeC.

Нет, не будет. Шаблоны проверяются во время компиляции.

Шаблонные функции генерируют функции во время компиляции. Шаблонные классы генерируют классы во время компиляции.

Вы можете быть смущены обобщениями в Java / C #, которые вдохновлены и служат некоторым целям шаблонов и гораздо более основаны на времени выполнения.

Эквивалент C ++ Generics - это классы стирания типов, такие как функция std. При этом используются шаблоны для создания связующего кода, который язык Java / C # делает для вас, когда вы примерно взаимодействуете с Generics. Я хотел бы сделать это (создание вспомогательных типов ластика типов, в отличие от простого использования функции std), чтобы использовать C ++ более продвинуто. В Java / C # есть несколько вариантов использования Generics, которые требуют этого в C ++ однако большинство вариантов использования Generics можно эмулировать в C ++ с помощью стандартного кода шаблона болота.

...