在Interface中覆盖模板成员

tea*_*ode 7 c++ templates

是否可以使用模板方法声明某种类型的基类,我可以在派生类中重写它?以下示例:

#include <iostream>
#include <stdexcept>
#include <string>

class Base
{
public:
    template<typename T>
    std::string method() { return "Base"; }
};

class Derived : public Base
{
public:
    template<typename T>
    std::string method() override { return "Derived"; }
};

int main()
{
    Base *b = new Derived();
    std::cout << b->method<bool>() << std::endl;
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

我希望Derived作为输出,但它是Base.我假设有必要创建一个模板化的包装类,它接收实现类作为模板参数.但我想确定一下.

Mar*_* A. 7

1)为了具有多态性,你的函数应该用虚拟标记

2)模板化的函数在POI处实例化,不能是虚拟的(签名是什么?你保留了多少个vtable条目?).模板化函数是编译时机制,虚函数是运行时机制.

一些可能的解决方案包


iav*_*avr 6

模板方法不能是虚拟的。一种解决方案是使用静态多态性来模拟“模板虚拟”方法的行为:

#include <iostream>
#include <stdexcept>
#include <string>

template<typename D>
class Base
{
    template<typename T>
    std::string _method() { return "Base"; }
public:

    template<typename T>
    std::string method()
    {
       return static_cast<D&>(*this).template _method<T>();
    }
};

class Derived : public Base<Derived>
{
    friend class Base<Derived>;

    template<typename T>
    std::string _method() { return "Derived"; }
public:
    //...
};

int main()
{
    Base<Derived> *b = new Derived();
    std::cout << b->method<bool>() << std::endl;
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

其中method是接口,_method是实现。要模拟纯虚拟方法,_method将缺少Base.

不幸的是,这种方式Base改变了,Base<Derived>所以你不能再拥有一个容器Base*.

另请注意,对于const方法,static_cast<D&>更改为static_cast<const D&>. 类似地,对于右值引用 ( &&) 方法,它会更改为static_cast<D&&>