存储std :: shared_ptr <foo>的向量,其中Foo是模板化的类</foo>

时间:2011-04-26 03:28:31

标签: c++ templates polymorphism double-dispatch

我有一个基类,我做了一个模板,因为我想改变几个函数所需的类型,但我想从这些模板化的基类派生。我想存储这些类的向量。我的想法是在层次结构中的所有内容之上创建一个非模板化的基类,并使用双重调度来计算类型。我这样做是“正确的方式”吗?

以下是该方案的代码段:

class FooBase
{
public:
    virtual void Accept( Visitor &v );
};

template<class T>
class Foo : public FooBase
{
public:
    virtual void DoThing( const T & );
    virtual void Accept( Visitor &v) = 0;

};

template<>
class Foo<Bar> : public FooBase
{
public:
    virtual void Accept( Visitor &v )
    {
        v.HandleBar( *this );
    }
};

template<>
class Foo<Baz> : public FooBase
{
public:
    virtual void Accept( Visitor &v )
    {
        v.HandleBaz( *this );
    }
};

//来自Foo,Foo的许多派生类

然后在另一个班级

class Visitor
{
public:
    virtual void HandleBar( Foo<Bar> &f ) = 0;
    virtual void HandleBaz( Foo<Baz> &f ) = 0;
};

class Manager : public Visitor
{
public:
    void AddFoo( FooBase& f )
    {
        a.push_back( f );
    }

    void RunAll()
    {
        for ( std::vector<std::shared_ptr<FooBase> >::iterator it = a.begin(); it != a.end(); ++it )
        {
            (*it)->Accept( *this );
            // do common action that doesn't depend on types
        }
    }

    virtual void HandleBar( Foo<Bar> &f )
    {
         Bar item = GetBarItemFunction(); // not shown
         f.DoThing( item );
    }
    virtual void HandleBaz( Foo<Baz> &f )
    {
         Baz item = GetBazItemFunction(); // not shown
         f.DoThing( item );
    }

private:
    std::vector<std::shared_ptr<FooBase> > a;
};

我只是不知道这是否是“最佳”方式。我可以使用dynamic_casting,但感觉很脏。那么这是一个可靠的解决方案吗?请指教(我希望我没有在示例中留下任何明显的语法错误)

(删除了EDIT,我这是个愚蠢的错误)

1 个答案:

答案 0 :(得分:3)

我想你差不多了。我会写访客类,如:

class Visitor
{
public:
    virtual void HandleFoo( Foo<Bar> &f ) = 0;
    virtual void HandleFoo( Foo<Baz> &f ) = 0;
    //default implementation for unknown Foo types:
    virtual void HandleFoo( FooBase &f ) = 0; 
};

现在您不需要专门化您的模板化Foo类,您只需编写以下内容即可使用您的应用程序可能需要的所有类T.将根据Foo中使用的模板类型选择正确的重载HandleFoo函数。您仍然需要向访问者类添加方法,以避免调用默认行为。

template<class T>
class Foo : public FooBase
{
public:
    virtual void DoThing( const T & );
    virtual void Accept( Visitor &v) {
        v.HandleFoo( *this );
    };
};