【问题标题】:Use templates to generate pure virtual base class methods使用模板生成纯虚拟基类方法
【发布时间】:2015-07-12 17:19:34
【问题描述】:

这听起来有点奇怪,我可能不得不在某些时候重构我的代码,但我需要使用模板函数生成纯虚拟基类方法。使用 C++11(可变参数模板?)是否可行?

例子:

struct I
{
    virtual void foo(int) = 0;
    virtual void foo(float) = 0;
};

struct S : public I
{
    template<typename T>
    void foo(T t) { /*do the same symbolic stuff on t*/ } 
};

int main()
{
    S s;
    s.foo(0);
    s.foo(0.0f);
    return 0;
}

给出以下错误(clang):

main.cpp:65:7: error: variable type 'S' is an abstract class
    S s;
      ^
main.cpp:53:18: note: unimplemented pure virtual method 'foo' in 'S'
    virtual void foo(int) = 0;
                 ^
main.cpp:54:18: note: unimplemented pure virtual method 'foo' in 'S'
    virtual void foo(float) = 0;
                 ^
1 error generated.

【问题讨论】:

    标签: c++ templates c++11 pure-virtual


    【解决方案1】:

    你不能直接做,但你可以使用转发器有一个通用的实现:

    struct S : public I
    {
    private:
        template<typename T>
        void foo_impl(T t) { /*do the same symbolic stuff on t*/ } 
    public:
        virtual void foo(int v) { foo_impl(v); }
        virtual void foo(float v) { foo_impl(v); }
    };
    

    【讨论】:

    • 谢谢,但您仍然必须使用相同的符号内容来实现虚拟方法,即使已分解...:/
    • @matovitch 如果您特别受虐,您也可以使用 CRTP 来执行此操作,假设有多个 S 可能正在做同样的事情,这可能值得考虑,因为它可以减轻轮子- 不止一次的改造。
    • @matovitch 当然可以,但是它们是简单的单行代码,而 foo_impl 可能更复杂,因此您仍然可以提高可维护性,避免将来在重构时出错。
    • @WhozCraig 你能详细说明一下吗...CRTP 是将派生类作为基类的模板参数传递的技巧不是吗?也许你应该回答? ;)
    • @matovitch 你非常成功,听起来你明白了。它与此答案的前提相同(提供一个调用您的模板的实现,同时实现流程中的纯基础)。但是该实现可以在派生自I 的CRTP 基础中,S 和您希望的任何其他类都可以作为基础。 Something like this。至少,您只需为所有派生实现一次实际的呼叫转发,只要它们实现正确的foo_impl 模板成员。
    【解决方案2】:

    你不能这样做。

    模板方法的签名与非模板方法的签名不同。

    而且你不能有一个虚拟模板方法。

    【讨论】:

    • 啊,感谢您指出 virtual 的问题...我认为您总是可以用 final 覆盖纯虚拟方法,所以您不能?
    • 可以,但不能使用模板。 void foo(int) 不等同于 void foo(T) 不管你怎么读...模板成为方法名的一部分。
    • 是的不等效...但我会想象编译器会查看基类并尝试实现 foo 的模板特化...遗憾的是事实并非如此...再次感谢为您提供帮助。
    猜你喜欢
    • 2013-10-07
    • 1970-01-01
    • 2015-03-31
    • 1970-01-01
    • 2015-12-09
    • 2011-03-20
    • 2020-10-21
    • 1970-01-01
    相关资源
    最近更新 更多