我有一个用c++编写的相当大的软件项目。
在这里,有一个class foo,它表示一个结构(我并不是指程序员结构),其中foo-objects可以成为foo-object的一部分。
下面是最简单的class foo:
class Foo
{
private:
std::vector<unsigned int> indices;
public:
void addFooIndex(unsigned int);
unsigned int getFooIndex(unsigned int);
};每个foo-object当前都存储在class bar的一个对象中。
class Bar
{
private:
std::vector<Foo> foos;
public:
void addFoo(Foo);
std::vector<Foo> getFoos();
}因此,如果foo-object应该表示带有“内部”foo对象的结构,我目前就会这样做。
Foo foo;
Foo innerFoo;
foo.addFooIndex(bar.getFoos().size() - 1);
bar.addFoo(innerFoo);为了得到它,我显然是用:
Foo foo;
for ( unsigned int i = 0; i < foo.getFooIndices().size(); ++i )
{
Foo inner_foo;
assert( foo.getFooIndices().at(i) < bar.getFoos().size() );
inner_foo = bar.getFoos().at(foo.getFooIndices().at(i));
}所以这不是问题。只是起作用了。但这不是最优雅的解决方案。
我现在想让内在的foos与foo-object“更紧密地联系”。显然,应该将class foo更改为:
class Foo
{
private:
std::vector<Foo*> foo_pointers;
public:
void addFooPointer(Foo*);
std::vector<Foo*> getFooPointers();
};因此,现在,对于我的问题:如何温和地更改这个基本类而不破坏整个代码呢?有没有一条“干净的路”?
发布于 2012-05-09 12:12:35
我来试试这个。
归根结底,你想要/需要什么样的内存管理。您可以将指针存储在Foo中,也可以存储Foo对象中。既然你说你不需要bar,因为它目前“拥有”Foo的内存,所以我建议您将它们直接放在Foo中:
class foo
{
public:
add_child(foo child); //Foo by value. Utilize 'move' semantics if copy is not possible.
const std::vector<foo>& get_children(); //Get a reference to the children. Could use iterators or whatever.
private:
std::vector<foo> foos;
}用法:
foo parent;
foo child;
foo grand_child;
child.add_child(std::move(grand_child)); //move semantics.
parent.add_child(child); //no move semantics.
parent.traverse(root);
void traverse(foo root)
{
root.discombobulate_the_parafunctors(); //act on root
auto children = root.get_children();
std::for_each(children.begin(), children.end(), traverse);
}这就是我想要做的,但你说你想“温柔地”做--我猜你是说渐进的,而不是破坏东西?由于在上面的示例中,所有权从bar转移到foo,因此不可能同时使用这两种方式。然而,指针方法可以分层在现有的bar实现之上。
如果我真的想“轻轻地”切换,我会使用指针创建一个类似于foo_tree_view的类,它类似于您的第一种方法,而不是假定所有权。我会从给定的bar实例构建它,然后在客户端代码中使用它。
std::vector<foo_tree_view> bar_view;
class foo_tree_view
{
public:
foo_tree_view(foo this_foo, bar source);
std::vector<foo*> get_children();
private:
...
}此时,您开始温和地更改所有位置,以使用这个新的foo_tree_view类。当所有代码都使用它时,您将更改为foo_tree_view的实现,以使用上述实现,而不使用“bar”,并将其重命名为foo。
希望你能理解这个答案!
发布于 2012-05-08 23:22:22
我不认为让foo对象负责容器中的索引是个好主意。它应该是幸福的不知道它在里面的容器(S)。维护这些索引是容器的工作(如果它适用于该容器)。
您当前的代码需要一个foo从bar检索内部foos,那么为什么不直接从foo中检索它们呢?
for (unsigned int index = 0; index < foo.getFooPointers().size(); ++index)
{
Foo* inner_foo = foo.getFooPointers().at(index);
}为什么你需要内部的foos存储在bar中?如果在某些情况下,您想遍历所有的foos,包括内部的,您可以创建一个迭代器。
另外,我可能会调用成员函数,类似于getInnerFoos()或getChildren(),而不是getFooPointers()。签名已经告诉您它返回foo类型的指针。
https://softwareengineering.stackexchange.com/questions/147801
复制相似问题