C++模板与继承

4

我能用这种方式混合使用继承和模板吗?:

template <class T> 
class AbstractType { // abstract
//....
}

template <class T> 
class Type1 : public AbstractType<T> {
//....
}

以后,我可以像这样使用这些类吗:
AbstractType<SomeClass>* var1 = new Type1<SomeClass>();

谢谢你的帮助。

3个回答

7

虽然可以这样做,但它并不像你想的那么有用。你可以像下面这样定义结构:

#include <string>
#include <vector>
using namespace std;

template<typename Val>
class Base
{
public:
    virtual Val DoIt() const = 0;
};

template<typename Val>
class Derived : public Base<Val>
{
public:
    Derived(const Val& val) : val_(val) {};
    Val DoIt() const { return val_; }
protected:
    Val val_;
};

int main()
{
    Derived<string> sd("my string");
    string sd_val = sd.DoIt();

    Derived<float> fd(42.0f);
    float fd_val = fd.DoIt();
}

但是当你定义抽象基类型时,通常会想要一个它们的集合,并且能够通过基类指针调用以获得多态行为。如果将基类模板化,则无法做到这一点,因为每个模板参数的变化都会创建不同的类型。Base<int>Base<string>完全不同,你不能只获取一个指向任何一个的Base*
以下代码将无法编译:
vector<Base*> my_objs;

7

是的,你可以。你可以使用模板参数来做任何你想要的事情,并将其传递到包含的基本模板类中。


@Seba - <list> 已经允许使用自定义分配器。您希望修改哪些其他实现细节? - Steve Townsend
@Steve - 实现列表的方法有很多种。所以我想,例如,我可以将函数参数声明为抽象类型,并让用户决定使用哪种实现。我只是在想 :) - Sebastian Dusza
2
@Seba:我没有看到有任何强制使用基类的情况。通常是根据性能/接口的精确要求来选择容器,而STL为所述要求提供了最有效的实现。STL的设计思路与面向对象完全不同(并且更好)。 - Matthieu M.
2
@Seba:Matthieu M. 是对的。用接口的方式做就是面向对象的方式。STL 是基于模板的。只要你遵守 STL 列表的接口,就可以将一个列表替换为另一个列表,而无需在它们之间使用基类和虚方法。就像 Leonidas 曾经宣称的那样:“这就是模板!”... ^_^ ... - paercebal
2
@Seba:并不完全是这样(即使这是一个副作用)。泛型编程的真正重点是避免不必要的基类。面向对象编程都是关于基类和常见的重写方法。C++是多范式的,在当前情况下,泛型编程(具有类似的接口)比面向对象编程(共同的基类)更好地实现了它,并且耦合性更小。这里的“类似”一词非常重要:我没有写“完全相同的接口”。这不是一个错误。 - paercebal
显示剩余2条评论

1

您可以使用类模板中的任何类型,只要该类型与类定义兼容。

例如:

template<class T> struct S{
   T mt;
};

这样的结构体可以实例化为T = int,T = double,但不能为T = void。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接