【问题标题】:How do you overload templated function (specialized) in child class?如何在子类中重载模板函数(专门)?
【发布时间】:2011-08-11 21:43:48
【问题描述】:

我有一个带有模板函数的基类,该函数具有通用模板类型和专用版本。

#ifndef BASE_CLASS
#define BASE_CLASS

#include <iostream>

using namespace std;

struct Type1
{
};

struct Type2
{
};

class baseClass
{
    public:
    template<class Type>
    void doStuff(Type & t)
        {
        templateFunction(t);  
        }

    template<class Type>
    void templateFunction(Type & t);
};

template<class Type>
void baseClass::templateFunction(Type & t)
{
    cout << "This is the generic function!" << endl;
}

template<>
void baseClass::templateFunction(Type1 & t)
{
    cout << "This is the specialized function: - Type1" << endl;
}
#endif

我还有一个继承自“baseClass”的子类。但是,子类针对该专业化需要不同的功能。

#ifndef CHILD_CLASS
#define CHILD_CLASS

#include "BaseClass.h"

class ChildClass : public baseClass
{
    public:

};

template<>
void ChildClass::templateFunction(Type1 & t)
{
    cout << "We overloaded the specialized template function for type 1!" << endl;
}

#endif

以上不编译:

ChildClass.h:13:错误:没有在“ChildClass”中声明的成员函数“templateFunction” ChildClass.h:13:错误:无效的函数声明

如果我将“重载”功能更改为:

template<>
void baseClass::templateFunction(Type1 & t)
{
    cout << "We overloaded the specialized template function for type 1!" << endl;
}

我得到: ChildClass.h:13:错误:“void baseClass::templateFunction(Type&) [with Type = Type1]”的重新定义 BaseClass.h:36:错误:“void baseClass::templateFunction(Type&) [with Type = Type1]” 之前在这里声明过

如何在子类中正确重载专门的模板函数?

供参考,主要:

#include "BaseClass.h"
#include "ChildClass.h"

int main()
{
    Type1 first;
    Type2 second;

    baseClass theBaseClass;
    ChildClass theChildClass;


    theBaseClass.doStuff(first);
    theBaseClass.doStuff(second);

    theChildClass.doStuff(first);
    theChildClass.doStuff(second);

    return 0;
}

根据 Kerrek SB 的建议,我将 ChildClass 更改为:

#ifndef CHILD_CLASS
#define CHILD_CLASS

#include "BaseClass.h"
class ChildClass : public baseClass
{
    public:
    template<class Type>
    void templateFunction(Type & t);
};

template<>
void ChildClass::templateFunction(Type1 & t)
{
    cout << "We overloaded the specialized template function for type 1!" << endl;
}

#endif

输出:

This is the specialized function: - Type1
This is the generic function!
This is the specialized function: - Type1
This is the generic function!

我希望:

This is the specialized function: - Type1
This is the generic function!
We overloaded the specialized template function for type 1!
This is the generic function!

所以这仍然行不通。

【问题讨论】:

  • 模板函数不能是虚函数,您确定要在隐藏原始函数的同时重新定义派生类中的成员函数吗?您无法通过指向基址的指针访问重新定义的函数!如果你确定,你也应该将非特化声明添加到派生类中。
  • 我不需要访问 baseClass 的原始专用功能,不。至少对于任何给定的 ChildClass 实例。
  • 好吧,在那种情况下,我相信如果你在专门化它之前将函数的主模板声明添加到派生类中,你应该能够做到。
  • 重新编辑:您已为 templateFunction 添加了覆盖,但您正在调用 doStuff - 这不起作用。覆盖你实际调用的函数!基类函数应该如何知道派生类中的非虚拟覆盖?为什么要让你的生活如此复杂,从一个更简单的例子开始......

标签: c++ templates


【解决方案1】:

它仍然无法按您想要的方式工作的原因是该函数在父类中不是虚拟的。但是,不可能有虚拟模板功能。

我看到两个主要选项:

  • 按照 rhalbersma 的建议,将类本身设为模板,然后在子类中覆盖所需的方法(现在不是模板)。
  • 对于专用方法,只需编写一个新方法,使用不同的名称,即可满足您的任何需求。

但我相信有人会想出更好的主意... =)

【讨论】:

    【解决方案2】:

    你可以用这样的虚函数创建一个模板类:

    template<typename T>
    class B
    {
        virtual void f() { std::cout << "base template implementation \n"; }
    };
    
    template<>
    class B<Type1>
    {
        virtual void f() { std::cout << "base specialized implementation \n"; }
    };
    
    template<typename T>
    class D: public B<T>
    {
        virtual void f() { std::cout << "derived template implementation \n"; }
    };
    
    template<>
    class D<Type1>: public B<Type1>
    {
        virtual void f() { std::cout << "derived specialized implementation \n"; }
    };
    
    B<Type1> b1;
    B<Type2> b2;
    D<Type1> d1;
    D<Type2> d2;
    
    b1.f();
    b2.f();
    d1.f();
    d2.f();
    

    现在有 2 个独立的自定义维度:模板 T 或动态类型(B vs D)。对于每个模板实例化,都可以重新定义虚函数。

    更常见的做法是让 B 为具有纯虚函数的常规类(即接口),让 D 为从 B 派生的模板类。这让您可以为每个模板以不同的方式重新定义 B 的虚函数D 的实例化(具有合适的默认值)。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2015-06-15
      • 2021-06-21
      • 2022-12-13
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-02-20
      相关资源
      最近更新 更多