抽象类上的模板类

Template class on a abstract class

本文关键字:抽象类      更新时间:2023-10-16

所以我有一个类模板Foo:

template <typename T>
class Foo
{
public:
    Foo();
    ~Foo();
   //...
};

我有两个来自Foo类的派生类:

class FooDerived1 : public Foo<int>
{
public:
    FooDerived1 ();
    ~FooDerived1 ();
};
class FooDerived2 : public Foo<double>
{
public:
    FooDerived2 ();
    ~FooDerived2 ();
};

但现在我看到类模板正在一个抽象类IBar上使用,如下所示:

class Foo;
class IBar
{
public:
    virtual void placeFoo(Foo& foo) = 0; //error
    virtual void removeFoo(Foo& foo) = 0;
};

我知道我不能在抽象虚拟类中使用模板类

但是。。在这种情况下,我该怎么办

我真的需要像这样的IBar抽象类。。。

忘记使用模板类吗

选项1:使IBar本身成为一个模板类。

template <class T>
class Foo;
template <class T>
class IBar
{
public:
    virtual void placeFoo(Foo<T>& foo) = 0;
    virtual void removeFoo(Foo<T>& foo) = 0;
};

选项2:使所有Foo<T>都派生自一个通用的、非通用的FooBase

class FooBase
{
    // ...
};
template <typename T>
class Foo : public FooBase
{
public:
    Foo();
    ~Foo();
    //...
};
// ...
class FooBase;
class IBar
{
public:
    virtual void placeFoo(FooBase& foo) = 0;
    virtual void removeFoo(FooBase& foo) = 0;
};

两种解决方案的可行性取决于您实际对T类型的依赖程度。但是,当您将虚拟函数与模板混合使用时,您应该预料到这一点。有了选项1,您就不再有通用的接口类型了;对于选项2,FooBase不能为任何具有T相关参数的成员函数提供。


顺便说一句,不要忘记真实代码中的虚拟析构函数。

如果需要通用行为,请为Foo<>:的所有实例创建基类

class FooBase
{
    //common interface and data
};
template <class T>
class Foo : public FooBase
{
};

然后:

class FooBase;
class IBar
{
public:
    virtual void placeFoo(FooBase& foo) = 0; //ok
    virtual void removeFoo(FooBase& foo) = 0;
};

问题是,你试图混合模板(编译时)和动态多态性(运行时),这可能会有问题(这是你所说的"我知道我不能在抽象虚拟类中使用模板类"的意思吗?)。

为什么不坚持使用模板呢?

class IBar
{
public:
    template <class T>
    void placeFoo(Foo<T>& foo);
    template <class T>
    void removeFoo(Foo<T>& foo);
};

或:

template <class T>
class IBar
{
public:
    void placeFoo(Foo<T>& foo);
    void removeFoo(Foo<T>& foo);
};