class compare_class {
public:
bool operator()(int A, int B) const {
return A < B;
}
};
...
// Declaration of C++ sorting function.
template <class ComparisonFunctor>
void sort_ints(int* begin_items, int num_items, ComparisonFunctor c);
...
int main() {
int items[] = {4, 3, 1, 2};
compare_class functor;
sort_ints(items, sizeof(items)/sizeof(items[0]), functor);
}
首先我想知道如果在sort_ints中提到了仿函数而没有任何括号,A和B参数如何传递给operator()(int A,int B)。
然后我想到A和B被传递给sort_ints函数内的函数对象。但那么,sort_ints的声明是否应该使用'ComparisonFunctor * * * c'而不是'ComparisonFunctor c',因为它接收函数的地址?
在sort_ints函数中,函数调用函数是否会像这样完成?
functor(*begin_items, *(begin_items+1));
答案 0 :(得分:6)
要理解为什么sort_ints
按值获取其参数,您必须记住,作为比较器传递给它的对象不一定是函数指针。例如,如果您使用compare_class
函数对象进行比较,那么您传递给函数的是compare_class
类型的具体对象。您没有传递compare_class::operator()
的地址,因为operator()
是成员函数,而不是自由函数。也就是说,以下代码:
compare_class myComparator;
myComparator(a, b);
转换为
compare_class myComparator;
myComparator.operator() (a, b);
因此,参数需要通过值而不是指针来接收比较器,因为它需要一个接收器对象,而不是指向成员函数的指针或指向接收器对象的指针。
答案 1 :(得分:3)
正如您所指出的那样,sort_ints的使用没有任何暗示其对比较函数的要求:
compare_class functor;
sort_ints(items, sizeof(items)/sizeof(items[0]), functor);
sort_ints本身也没有:
template <class ComparisonFunctor>
void sort_ints(int* begin_items, int num_items, ComparisonFunctor c);
在class_compare中,我们只能推断出观察它将使用的功能不提供其他功能:
class compare_class
{
public:
bool operator()(int A, int B) const { return A < B; }
};
编译器确实离开它,直到它尝试编译sort_ints的实现,使用它实例化的类型,然后才能确定这是否全部挂起。 sort_ints必须具有你提到的那种陈述:
c(*begin_items, *(begin_items+1)); // note: functor argument is "c"
所以,你的理解在所有方面都是正确的。但是,值得注意的是,所提出的名为Concepts的C ++ 0x特性旨在使sort_int的要求更加明确,而无需考虑其实现。不幸的是,C ++ 0x不得不放弃这个功能,因为没有足够的时间和经验来确保它是最佳的。希望C ++的未来版本将包含这样的功能。您可以在'网上找到很多关于概念的讨论,它们应该可以帮助您更好地理解整体问题。
这是一个重要的问题,因为当你只有一些拼图 - 比如你想要使用的sort_ints函数但没有示例ComparisonFunctor时,你必须研究sort_ints的实现,以了解如何创建该Functor(除非你是超级幸运的,有很好的,现有的文件)。您可能会意外地使您的代码过于依赖现有的实现,因此当sort_int的实现稍后更改时,您的代码会无法接受地破坏或减慢 - 即使它足够巧妙,不会破坏测试用例或其他用户的代码或期望。所提供的ComparisonFunctor中的一个小错误也可能会从sort_int的内容中产生一个非常复杂且令人困惑的编译器错误消息 - 这不是向用户提供抽象服务的好方法。让我们希望Concepts能在一天之内完成......!
答案 2 :(得分:2)
请注意,compare_class
是一个类。所以它可以声明,以你使用其他类的方式作为函数参数传递。
其次,compare_class
实施operator()
。这允许您执行以下操作:
compare_class obj;
obj(1, 2);
现在,上面代码片段中的第二个语句看起来像一个函数调用!所以从某种意义上说,实现operator()
的类的任何对象都可以像函数一样使用。
这是功能对象的重点。此外,它还有其他优于函数指针的优点,您可以在帖子中找到相同的链接。
修改强>
在sort_ints()
内,仿函数应该执行以下操作:
for (int i = 1; i < num_items; i++)
if (c(begin_items[i-1], begin_items[i]))
{
// begin_items[i-1] is less than begin_items[i], do stuff
}
答案 3 :(得分:1)
是的,这是正确的。函数调用运算符应用于对象的名称,而不是对象的方法。此外,您没有传递函数的地址,而是传递(复制)对象。仿函数对象没有数据成员,只有operator()。