具有不同数据类型的纯虚方法

时间:2011-04-15 12:02:55

标签: c++ oop templates inheritance virtual-method

我正在为我的容器类创建一个基类,因此我可以维护一致的接口。它目前看起来像这样:

template <typename Datatype>
class BaseClass
{
    public:
    virtual Datatype Foo() = 0;
    virtual Datatype Bar() = 0;
};

template <typename Datatype>
class DerivedClass: public BaseClass<Datatype>
{
    public:

    virtual Datatype Foo()
    {
    }

    virtual Datatype Bar()
    {
    }
};

但是,对于某些派生类,Foo()Bar()可能需要彼此具有不同的返回类型。如果基类中没有每个不同返回类型的模板参数,我如何为派生类提供一些改变这种东西的空间?

编辑:

派生类使用的类型可能完全不同且不变。实际上,除了方法名称之外,派生类不能保证有任何共同点。

6 个答案:

答案 0 :(得分:6)

提供专门针对您需要不同结果的情况的特质。

template <typename Datatype>
struct BaseTraits
{
    typedef Datatype FooResult;
    typedef Datatype BarResult;
};

template <typename Datatype, typename Traits = BaseTraits<Datatype> >
class BaseClass
{
    public:
    virtual Traits::FooResult Foo() = 0;
    virtual Traits::BarResult Bar() = 0;
};

答案 1 :(得分:3)

如果您提前知道潜在类型的数量,可以通过向基类模板添加其他类型来扩展您所拥有的类型......

template <typename FOO_TYPE,typename BAR_TYPE>
class BaseClass
{    
public:    
    virtual FOO_TYPE Foo() = 0;    
    virtual BAR_TYPE Bar() = 0;
};

template <typename FOO_TYPE,typename BAR_TYPE>
class DerivedClass: public BaseClass<FOO_TYPE,BAR_TYPE>
{    
public:    
    virtual FOO_TYPE Foo()    {    }    
    virtual BAR_TYPE Bar()    {    }
};

如果您有多种类型,这可能会失控。

答案 2 :(得分:1)

如果返回类型是共变体,可以更改它们,或者您可以编写某种转换函数,并且有real_bar或类似的东西。

答案 3 :(得分:1)

traits可能有所帮助。 C++ Templates - The Complete Guide一书提供了一个示例,在标题为特征和策略类的章节中对此进行了说明。它有一个使用累加器返回不同类型的例子。

编辑:我可以看到AProgrammer已经举了一个例子

答案 4 :(得分:1)

return不同的数据类型是不可能的。唯一的方法是制作方法template,因为virtual方法不能是模板,所以方法是限制的。

答案 5 :(得分:1)

#include <iostream>
#include <typeinfo>

using namespace std;

template <typename T, typename R = T>
class base
{
  public:
    virtual R foo() 
    {
      cout << "foo(): data type = " << typeid(T).name() << endl; return R();
    }

    virtual R bar()
    {
      cout << "bar(): return type = " << typeid(R).name() << endl; return R();
    }
};

int main()
{
  base<int> b;
  base<int, long> b1;

  b.foo(); b.bar();
  b1.foo(); b1.bar();

  cout << typeid(b).name() << endl;
  cout << typeid(b1).name() << endl;

  return 0;
}

上述程序返回以下内容:

使用g++

$ ./rettypetemplate
foo(): data type = i
bar(): return type = i
foo(): data type = i
bar(): return type = l
4baseIiiE
4baseIilE

使用Visual Studio 2005 cl.exe

C:\Program Files\Microsoft Visual Studio 8\VC>rettypetemplate.exe
foo(): data type = int
bar(): return type = int
foo(): data type = int
bar(): return type = long
class base<int,int>
class base<int,long>

尽管此示例显示了如何执行此操作,但AProgrammer给出的答案显示了使用特征处理它的好方法。上面的示例适用于基本数据类型,但不适用于用户定义的类型。要处理用户定义的类型,特征是要走的路。请参阅Jossutis的"The C++ Template" book或“Modern C++ design”以了解有关特征的更多信息。