专门化模板类时的继承

时间:2015-05-26 12:20:38

标签: c++ templates

我希望能够做到这样的事情:

template<typename T>
class myClass{
    public:
        double Foo(double x){return x;}
}

template<>
class myClass<SpecialType>{
    public:
        double Bar(double x){return x+1.0;}
}

现在,我想实例化专业化,但仍然可以访问方法Foo而无需在专业化中重写整个内容,即:

myClass<SpecialType> A;
double y = A.Foo(1.0);

有没有办法在我当前的设置中执行此操作,或者我是否需要编写&#34; master&#34; class是为了继承Foo()

2 个答案:

答案 0 :(得分:1)

您可以重复专业化中的公共部分

template<typename T>
class myClass
{
public:
    double Foo(double x){return x;}
};

template<>
class myClass<SpecialType>
{
public:
    double Foo(double x){return x;}
    double Bar(double x){return x + 1.0;}
};

或使用其他助手类:

template<typename T> struct BarHelper<T> {};
template<> struct BarHelper<SpecialType>
{
    double Bar(double x) {return x + 1.0;}
};

template<typename T>
class myClass : public BarHelper<T>
{
public:
    double Foo(double x){return x;}
    // inherit Bar method for SpecialType.
};

答案 1 :(得分:1)

两个选项(多个选项):

  • 构造一个公共基类,在其中放置所有与类型无关的东西(推荐):

    struct myClassBase
    {
        virtual double Foo(double x) const {return x+1.0;}
    };
    
    template<typename T> struct myClass : public myClassBase
    {
         //...
    };
    
    template<>
    struct myClass<SpecialType> : public myClassBase
    {
        double Bar(double x){return x+1.0;}
    }
    

    特别是当您的功能不依赖于模板参数时,建议使用此功能。

  • 从您的非专业课程中导出:

    template<>
    struct myClass<SpecialType> : public myClass</* be careful what to write here */>
    {
        double Bar(double x){return x+1.0;}
    }
    

    但是,您必须小心,将哪种类型传递给非专用类模板(特别是当您的成员函数依赖于模板类型时 - 为了理解它们应该以某种方式应该这样)。

  • 另一个更静态的选择是应用strategy pattern:将所有功能转移到一些小型策略类,然后通过组合构建所需的类(缺点:你必须再次公开这些函数) ,或通过多重继承(这里你不必重述整个事情,但要小心避免含糊不清)。

编辑:根据您的评论,以下是执行相同任务的CRTP方法:

template<typename Derived>
struct myClassBase
{
    double Foo(double x) const
    {
        return static_cast<Derived const&>(*this).specialMember(x);
    }
    //all other stuff independent of the derived class specialization

    //possibly define specialMember once:
    virtual double specialMember(double x) const { return x; }
}

template<typename T> struct myClass : public myClassBase<myClass<T> >
{
    //... special member of Base class is sufficient
};

template<> struct myClass<SpecialType> : public myClassBase<myClass<SpecialType> >
{
    virtual double specialMember(double x) const { return x+1.0; }
};

请注意,只有在模板类型真正参与评估功能时,这才有意义。

另一方面,如果double Foo(double x)上的重载已足够,请忘记整个模板内容并使用第一个替代方案。