只能由函数本身写入的函数参数-递归计数器

时间:2019-04-14 10:41:45

标签: c++ recursion

因此,我正在尝试编写一个递归函数,以跟踪该函数被调用的频率。由于其递归性质,我将无法在其内部定义迭代器(或者是否可以通过指针?),因为只要调用该函数便会对其进行重新定义。所以我想我可以使用函数本身的参数:

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)。

5 个答案:

答案 0 :(得分:3)

您可以按原样使用它并包装它。我想到的一种完全封装包装的方法是使您的函数成为本地类的静态成员。演示:

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的控制。

答案 1 :(得分:2)

如果您可以使用自由函数以外的其他功能,我建议您使用某种函子来保存计数,但是如果您不能这样做,则可以尝试使用类似这样的功能通过友谊来完成: / p>

#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);
}

答案 2 :(得分:1)

您可以封装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);

答案 3 :(得分:1)

执行此操作的一种方法是使用仿函数。这是一个简单的示例:

#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

由于计数存储在对象本身中,因此用户无法覆盖它。

答案 4 :(得分:-3)

您是否尝试过使用“静态”计数器变量。静态变量仅初始化一次,并且是用作计数器变量的最佳候选。