所以我正在尝试编写一个递归函数来跟踪它被调用的频率。由于它的递归性质,我将无法在其中定义迭代器(或者可能通过指针?),因为每当函数被调用时它都会被重新定义。所以我想我可以使用函数本身的参数:
int countRecursive(int cancelCondition, int counter = 0)
{
if(cancelCondition > 0)
{
return countRecursive(--cancelCondition, ++counter);
}
else
{
return counter;
}
}
现在我面临的问题是,counter
可以被函数的调用者写入,我想避免这种情况。再说一遍,将counter
宣布为const
无济于事,对吧?有没有办法将变量的操作限制为函数本身?或者也许我的方法在一开始就存在严重缺陷?
我能想到解决这个问题的唯一方法是使用一种“包装函数”来跟踪调用递归函数的频率。
我想避免的一个例子:
//inside main()
int foo {5};
int countToZero = countRecursive(foo, 10);
//countToZero would be 15 instead of 5
使用我的功能的用户不应该初始设置计数器(在这种情况下为10)。
您可以按原样运行,并将其包装。我想到的一种方法是完全封装包装,这是通过使你的函数成为本地类的静态成员。展示:
int countRecursive(int cancelCondition)
{
struct hidden {
static int countRecursive(int cancelCondition, int counter = 0) {
if(cancelCondition > 0)
{
return countRecursive(--cancelCondition, ++counter);
}
else
{
return counter;
}
}
};
return hidden::countRecursive(cancelCondition);
}
本地类是C ++的一个漂亮但很少见的特性。它们有一些限制,但幸运的是可以有静态成员函数。没有来自外部的代码可以传递hidden::countRecursive
无效的counter
。它完全在countRecursive
的控制之下。
如果你可以使用其他东西而不是自由函数,我建议使用某种仿函数来计算,但如果你不能,你可以尝试使用友谊来做这样的事情:
#include <memory>
class Counter;
int countRecursive(int cancelCondition, std::unique_ptr<Counter> counter = nullptr);
class Counter {
int count = 0;
private:
friend int countRecursive(int, std::unique_ptr<Counter>);
Counter() = default; // the constructor can only be call within the function
// thus nobody can provide one
};
int countRecursive(int cancelCondition, std::unique_ptr<Counter> c)
{
if (c == nullptr)
c = std::unique_ptr<Counter>(new Counter());
if(cancelCondition > 0)
{
c->count++;
return countRecursive(--cancelCondition, std::move(c));
}
else
{
return c->count;
}
}
int main() {
return countRecursive(12);
}
你可以封装counter
:
struct counterRecParam {
counterRecParam(int c) : cancelCondition(c),counter(0) {}
private:
int cancelCondition;
int counter;
friend int countRecursive(counterRecParam);
};
现在调用者无法修改计数器,您只需要稍微修改一下这个函数:
int countRecursive(counterRecParam crp)
{
if(crp.cancelCondition > 0)
{
--crp.cancelCondition;
++crp.counter;
return countRecursive(crp);
}
else
{
return crp.counter;
}
}
隐式转换允许您使用int
调用它
counterRecursive(5);
一种方法是使用仿函数。这是一个简单的例子:
#include <iostream>
class counter
{
public:
unsigned operator()(unsigned m, unsigned n)
{
// increment the count on every iteration
++count;
// rest of the function
if (m == 0)
{
return n + 1;
}
if (n == 0)
{
return operator()(m - 1, 1);
}
return operator()(m - 1, operator()(m, n - 1));
}
std::size_t get_count() const
{
return count;
}
private:
// call count
std::size_t count = 0;
};
int main()
{
auto f = counter();
auto res = f(4, 0);
std::cout << "Result: " << res << "\nNumber of calls: " << f.get_count() << std::endl;
return 0;
}
输出:
Result: 13
Number of calls: 107
由于计数存储在对象本身中,因此用户无法覆盖它。
您是否尝试过使用“静态”计数器变量。静态变量只被初始化一次,并且是用作计数器变量的最佳候选者。