确保在编译时,派生自抽象基类的所有类均实现特定的构造函数签名

时间:2019-07-03 16:38:53

标签: c++ templates constructor polymorphism abstract-class

我有一个抽象基类,以及可能从其继承的多个对象。例如

    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();
    }    

两个子类ModeAModeB的构造函数带有参数(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行,包括检查列表中的值,如果不匹配则删除并重新创建-这个简单的工作示例中遗漏了很多东西)

如果我使用的是ModeAModeB,那很好,因为它们具有正确的构造函数。

我的问题是,我(或继承此代码的人)最终可能会创建一个新类型,而忘记放入这种形式的构造函数,例如

    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 :(得分:0)

  

在创建ModeC的功能模板时,如果我使用ModeC调用mode_maker,则会产生运行时错误。

不,不会。在编译时检查模板。

模板函数在编译时生成函数。模板类在编译时生成类。

您可能会对Java / C#中的泛型感到困惑,该泛型受模板的启发并满足模板的某些用途,并且更多地基于运行时。

C ++的泛型等效项是类型擦除类,例如std函数。当您与泛型进行交互时,它使用模板来创建Java / C#语言为您执行的粘合代码。我会考虑这样做(创建类型橡皮擦助手类型,而不是仅使用std函数)是C ++的高级用法。 Java / C#中有一些泛型用法,在C ++中需要这样做。不过,大多数用法都可以通过沼泽标准模板代码在C ++中进行仿真。