复杂类型的容器实现

时间:2012-09-10 11:16:27

标签: c++

我正在尝试提供一个容器包装器,它存储以下类型的数据:bool,int,double,std :: string。另外我有一个复杂的类型,我需要存储在容器中。我们称之为Foo。为简单起见,我们会说Foo包含一个整数列表。

我的容器类目前包含了一个丑陋而复杂的容器类型,我从c api中获取它。当我完成对容器中数据的操作时,我需要将其复制回api。它使用工会和链接列表。我可以将此数据复制到例如std :: list中,但这可能会导致性能问题,这些问题会在以后出现。因此,我的容器类不依赖于数据实际存储在内存中的方式。

以下是我的容器外观的简要概述:

template <class T>
class Cont
{
public:
    Cont(ISetter<T>* setter)
        : _setter(setter)
    {
    }

    void sillyFunction(T t)
    {
        (*_setter)(t,0);
    }

private:
    ...
    ISetter<T>* _setter;
};

所以我使用一个辅助setter类来处理内存的细节。我有很多这样的课,但ISetter会让你知道我在做什么。

为了处理由c api以相当奇怪的方式存储的Foo类型,我已经到达了下面的setter。同样,这只是一个粗略的例子。

class IFoo
{
public:
    virtual int getMember() = 0;
};

class Foo2: public IFoo
{
public:
    virtual int getMember(){ return 1;} // dummy 
};

template<typename T> class ISetter{};
template<> class ISetter<IFoo*>
{
public:
    virtual void operator()(IFoo* value, int index) = 0;
};

template<typename T> class Setter{};
template<> class Setter2<Foo2*>: public ISetter<IFoo*>
{
public:
    virtual void operator()(IFoo* value, int index)
    {
        _list[index] = dynamic_cast<Foo2*>(value);
    }

private:
    std::vector<Foo2*> _list;
};

所以我将我的Foo作为一个名为IFoo的接口来处理。 Setter2实现处理我的Foos列表的内存设置。下面缺少的Setter1处理丑陋的c api记忆。

以下是实践中这些课程的概念:

Foo2* f = new Foo2();
ISetter<IFoo*>* setter = new Setter2<Foo2*>();
Cont<IFoo*>* container = new Cont<IFoo*>(setter);
container->sillyFunction(f); 

例如,在处理整数时,我会这样做:

int i = 10;
ISetter<int>* setter = new Setter1<int>();
Cont<int>* container = new Cont<int>(setter);
container->sillyFunction(i);

所以,我的问题是,如果你认为这是一个很好的方法,你可能会推荐哪些改进。

我使用共享指针而不是原始指针。

2 个答案:

答案 0 :(得分:1)

我将创建一个简单的Foo包装类,它可以从C API中查找成员数据,并将其作为一个连贯的类来呈现。无需弄乱接口,虚函数或继承。只需一个班级即可。

因此,对于C API中的每个“Foo”-entry,您将创建一个Foo包装器。

然后,您可以使用简单,行为良好的类型来表示存储在C库中的数据的各个实例。

现在只需将其放入std::vector

struct Foo {
    Foo(<handle-or-pointer-to-library-data>);

    // member functions for retrieving member data from the C API
};


std::vector<int>
std::vector<bool>
std::vector<std::string>
std::vector<Foo>

据我了解你的问题,这将是一个简单而有效的解决方案。

答案 1 :(得分:1)

我会稍微改变一下。考虑从代码中删除所有这个Setter虚拟主义。引入模板的目标之一是替代虚拟主义:

template <class T, class Setter>
class Cont
{
public:
    Cont(Setter setter = Setter())
        : _setter(setter)
    {
    }

    void sillyFunction(T t)
    {
        _setter(t,0);
    }

private:
    ...
    Setter _setter;
};

简单用法:

template <class IType, class Type>
class Setter2_Virtual
{
public:
    void operator()(IType* value, int index)
    {
        _list[index] = dynamic_cast<Type*>(value);
    }

private:
    std::vector<Type*> _list;
};


Cont<IFoo*, Setter2_Virtual<IFoo, Foo2> > container;
container.sillyFunction(f); 

我专注于Setters - 但也许你也可以用IFoo / Foo的东西做同样的事情。

只是一个想法 - 毕竟你没有义务使用它。