我有一个类,其中包含另一个类对象的向量作为成员。 在此类的许多函数中,我必须对向量中的所有对象执行相同的操作:
class Small
{
public:
void foo();
void bar(int x);
// and many more functions
};
class Big
{
public:
void foo()
{
for (size_t i = 0; i < VectorOfSmalls.size(); i++)
VectorOfSmalls[i]->foo();
}
void bar(int x)
{
for (size_t i = 0; i < VectorOfSmalls.size(); i++)
VectorOfSmalls[i]->bar(x);
}
// and many more functions
private:
vector<Small*> VectorOfSmalls;
};
我想简化代码,并找到一种方法不重复每个函数中的其他向量。
我考虑过创建一个函数,该函数接收指向函数的指针,并在向量的每个成员上调用指向的函数。 但我不确定在 C++ 中使用函数指针是个好主意。
我也一直在考虑函子和 functionoids< /a>,但这会迫使我为每个函数创建一个类,这听起来有点矫枉过正。
另一种可能的解决方案是创建一个接收字符串的函数,并根据该字符串调用命令:
void Big::call_command(const string & command)
{
for (size_t i = 0; i < VectorOfSmalls.size(); i++)
{
if (command == "foo")
VectorOfSmalls[i]->foo();
else if (command == "bar")
VectorOfSmalls[i]->bar();
}
}
void Big::foo()
{
call_command("foo");
}
但它可能运行缓慢(不需要创建字符串而不仅仅是函数调用),并且如果函数具有不同的签名,也会产生问题。
那么你会推荐什么? 我应该让一切保持现在的样子吗?
编辑:我只能使用 STL 而不能使用 boost(旧编译器)。
I have a class that has a vector of another class objects as a member. In many functions of this class I have to do same operation on all the objects in the vector:
class Small
{
public:
void foo();
void bar(int x);
// and many more functions
};
class Big
{
public:
void foo()
{
for (size_t i = 0; i < VectorOfSmalls.size(); i++)
VectorOfSmalls[i]->foo();
}
void bar(int x)
{
for (size_t i = 0; i < VectorOfSmalls.size(); i++)
VectorOfSmalls[i]->bar(x);
}
// and many more functions
private:
vector<Small*> VectorOfSmalls;
};
I want to simplify the code, and find a way not to duplicate going other the vector in every function.
I've considered creating a function that receives a pointer to function, and calls the pointed function on every member of a vector. But I am not sure that using pointers to functions in C++ is a good idea.
I have also been thinking about functors and functionoids, but it will force me to create a class per each function and it sounds like an overkill.
Another possible solution is creating a function that receives a string, and calls the command according to the string:
void Big::call_command(const string & command)
{
for (size_t i = 0; i < VectorOfSmalls.size(); i++)
{
if (command == "foo")
VectorOfSmalls[i]->foo();
else if (command == "bar")
VectorOfSmalls[i]->bar();
}
}
void Big::foo()
{
call_command("foo");
}
But it might work slow (unneeded creation of a string instead of just a function call), and also creates a problem if functions have different signature.
So what would you recommend? Should I leave everything the same as it is now?
EDIT: I can use only STL and not boost (old compilers).
发布评论
评论(3)
如果您使用的是 std 库,则应该查看 for_each 。
您提到在 C++ 中使用函数指针可能不是一个好主意,但是——让您担心的是速度——您必须在担心之前看看这是否是您所在的性能瓶颈区域。
If you're using the std library, you should take a look at for_each.
You mention that using function pointers in C++ might not be a good idea, but -- allowing your worry is speed -- you have to see if this is even a performance bottleneck area you're in, before worrying.
尝试 boost::function 和 boost::bind:
Try boost::function and boost::bind:
好吧,您可以重写 for 循环以使用迭代器和更多 STL,如下所示:
除此之外,您还可以使用一些宏来避免多次重新输入,但我不太喜欢这样做。 就我个人而言,我喜欢多个函数,而不是使用命令字符串的单个函数。 因为它为您提供了更多决策方式的灵活性。
如果你确实使用一个带有参数的函数来决定要做什么,我会使用一个枚举和一个像这样的开关,它会比字符串和级联 if 更有效。 另外,在您的示例中,您可以使用 if 来决定在循环内执行哪些操作。 在循环外部进行检查并拥有循环的冗余副本会更有效,因为每次调用只需决定一次“哪个命令”。 (注意:如果在编译时已知该命令,则可以将其设置为模板参数,听起来确实如此)。
另外,正如您所提到的,替换 &Small::whatever 成员函数指针并将其作为参数传递是相当简单的。 您甚至可以将其设为模板。
然后你可以这样做:
这个方法和常规参数方法的好处是,如果你改变较小的值以获得更多例程,则不需要改变 Big 值! 我认为这是首选方法。
如果您希望能够处理单个参数,您还需要添加一个bind2nd,这是一个完整的示例:
Well you can rewrite the for loops to use iterators and more of the STL like this:
beyond that, you could use some macros to avoid retyping that a lot, but I'm not a huge fan of that. Personally, I like the multiple functions over the single one which takes a command string. As it gives you more versatility over how the decision is made.
If you do go with a single function taking a param to decide which to do, I would use an enum and a switch like this, it would be more efficient than strings and a cascading if. Also, in your example you have the if to decide which to do inside the loop. It is more efficient to check outside the loop and have redundant copies of the loop since "which command" only needs to be decided once per call. (NOTE: you can make the command a template parameter if it is known at compile time, which it sounds like it is).
Also, as you mentioned, it is fairly trivial to replace the &Small::whatever, what a member function pointer and just pass that as a parameter. You can even make it a template too.
Then you can do:
The nice thing about both this and the regular parameter methods is that Big doesn't need to be altered if you change small to have more routines! I think this is the preferred method.
If you want to be able to handle a single parameter, you'll need to add a bind2nd too, here's a complete example: