我正在尝试提供一个容器包装器,它存储以下类型的数据: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);
所以,我的问题是,如果你认为这是一个很好的方法,你可能会推荐哪些改进。
我使用共享指针而不是原始指针。
答案 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的东西做同样的事情。
只是一个想法 - 毕竟你没有义务使用它。