1

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

我的容器类目前包装了我从 ac 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;
};

所以我使用了一个辅助设置器类来处理内存的细节。我有很多这样的课程,但 ISetter 会让您了解我在做什么。

为了处理 Foo 类型,它也是由 c api 以一种相当奇怪的方式存储的,我来到了下面的 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);

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

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

4

2 回答 2

1

我将创建一个简单的Foo包装类,它可以从 C API 中查找成员数据,并将其呈现为一个连贯的类。无需为此搞乱接口、虚函数或继承。只需一节课就可以了。

因此,对于 C API 中的每个“Foo”条目,您都创建了一个 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>

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

于 2012-09-10T13:10:10.410 回答
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 的东西做同样的事情。

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

于 2012-09-10T15:01:09.743 回答