代码之家  ›  专栏  ›  技术社区  ›  user997112

不使用虚拟方法静态执行C++类接口

c++
  •  -1
  • user997112  · 技术社区  · 6 年前

    我有一个父子班:

    class Parent
    {
        virtual void mustDefine() = 0;
    };
    
    class Child : public Parent
    {
        virtual void mustDefine(){}
    };
    

    我想强迫所有的儿童班 Parent 实施 mustDefine() . 但是,我的对象类型在编译时是已知的,因此我不希望进行多态的V表查找。

    是否有静态方法强制子类实现父方法?

    3 回复  |  直到 6 年前
        1
  •  3
  •   Lightness Races in Orbit    6 年前

    如果需要强制程序员通过在派生类中实现同名函数来隐藏基类成员函数…然后不定义基类成员函数。尝试调用它将导致链接器错误和生成失败。

    如果你的用户 不要 尝试调用该函数,则生成仍将工作,这对于虚拟函数来说不一定是正确的。但是你在乎这个吗?

    struct Parent
    {
        void mustDefine();
    };
    
    struct Child : Parent
    {
        // Link failure if this is missing, due to call in main().
        // That's because, without Child::mustDefine() hiding
        // Parent::mustDefine(), lookup for `mustDefine` will find
        // Parent::mustDefine() instead... which is, well, undefined.
        void mustDefine() {}
    };
    
    int main()
    {
        Child c;
        c.mustDefine();
    }
    
        2
  •  1
  •   UKMonkey    6 年前

    最明显的方法是使用模板,尽管我强烈建议您不要使用这样的代码:

    template<Impl>
    void thing(Impl thingy) {
        thingy.mustDefine();
    }
    

    结果将是IMPL必须具有“mustdefine”函数,否则您将得到编译错误,但这确实是一个维护噩梦。人们不知道IMPL真正是什么,当他们决定要写一个新的IMPL时,他们就不能列出需要实现的全部内容。

    我建议您尽管这是一个xy问题,但您不想调用虚拟方法的原因应该得到解决。

        3
  •  0
  •   Caleth    6 年前

    你不需要 class Parent 在这里。你有的是 Named Requirement

    class Child1
    {
        void mustDefine() { ... }
    };
    
    class Child2
    {
        void mustDefine() { ... }
    };
    
    class NotChild
    {
    };
    
    template<typename T>
    void usesMustDefine(T t)
    {
        t.mustDefine();
    }
    
    int main()
    {
        Child1 c1;
        Child2 c2;
        NotChild c3;
    
        usesMustDefine(c1); // Succeeds
        usesMustDefine(c2); // Succeeds
        // usesMustDefine(c3); // Fails
    
        c1.mustDefine(); // Succeeds
        c2.mustDefine(); // Succeeds
        // c3.mustDefine(); // Fails
    
        return 0;
    }