只能由函数本身进行写操作的函数参数 - 递归计数器
只能由函数本身进行写操作的函数参数 - 递归计数器
所以我正在尝试编写一个递归函数,以跟踪它被调用的次数。由于其递归性质,我将无法在其中定义一个迭代器(或者也许可以通过指针实现?),因为每次调用函数时都会重新定义它。所以我想我可以使用函数本身的一个参数:
int countRecursive(int cancelCondition, int counter = 0) { if(cancelCondition > 0) { return countRecursive(--cancelCondition, ++counter); } else { return counter; } }
现在我面临的问题是,counter
可以被函数的调用者写入,我想避免这种情况。
但是,将counter
声明为const
也无济于事,对吗?
有没有办法限制变量的操作只能在函数内部进行?
或者也许我的方法本来就是错误的?
我能想到的唯一解决这个问题的方法是使用一种“包装函数”,以跟踪递归函数被调用的次数。
我想避免的一个例子:
//在main函数中 int foo {5}; int countToZero = countRecursive(foo, 10); //countToZero将是15而不是5
使用我的函数的用户不应该能够最初设置计数器(在这种情况下为10)。
函数参数只能由函数本身写入的原因是为了保护参数的数据完整性和安全性。如果允许调用者直接修改参数,可能会导致参数被错误地修改或滥用,从而影响函数的正确性和可靠性。
为了解决这个问题,可以使用封装和隐藏的方法来限制调用者对参数的访问和修改。可以将参数封装在一个结构体中,并将其设置为私有成员。通过这种方式,调用者无法直接访问和修改参数,只能通过函数内部的控制逻辑来修改参数的值。
在上述代码示例中,通过定义一个名为counterRecParam的结构体来封装参数。结构体中包含了一个私有的cancelCondition变量和一个counter变量,通过友元函数的方式将countRecursive函数声明为可以访问和修改结构体的私有成员。
在countRecursive函数中,通过传递counterRecParam结构体的副本作为参数,实现了对参数的保护。在函数内部,通过递归调用自身的方式来修改和更新参数的值。当cancelCondition大于0时,递减cancelCondition并递增counter,然后再次调用countRecursive函数。当cancelCondition等于0时,返回counter的值作为结果。
此外,通过隐式转换的方式,还可以使用一个整数值作为参数调用countRecursive函数。这是因为counterRecParam结构体的构造函数定义了一个整数类型的参数,可以通过该参数创建一个counterRecParam对象,并将其作为countRecursive函数的参数传递。这样可以更方便地调用函数,而无需显式地创建和传递counterRecParam对象。
通过以上的封装和隐藏方法,可以有效地限制函数参数的访问和修改权限,提高函数的安全性和可靠性。这种方式可以在需要保护参数数据的情况下使用,确保函数的正确性和可靠性。
函数参数只能由函数本身写入的原因是为了限制外部对参数的修改,以确保函数的正确性和一致性。在递归函数中,计数器参数是一个很常见的需求,但是我们希望这个计数器参数只能由函数自身进行修改,以避免递归调用时对计数器的误操作。
为了解决这个问题,可以使用友元函数和智能指针来实现。在代码中,定义了一个名为Counter的类,其中包含一个私有的计数器count。通过将递归函数countRecursive声明为Counter的友元函数,使得countRecursive函数可以访问和修改Counter类的私有成员。同时,countRecursive函数的第二个参数使用了std::unique_ptr
在countRecursive函数中,首先判断计数器对象是否为空,如果为空则创建一个新的计数器对象。然后根据取消条件判断是否继续递归调用,如果需要继续递归调用,则计数器对象的count加1,并将cancelCondition减1,然后将计数器对象通过std::move传递给下一次递归调用。如果取消条件为0,表示递归结束,函数返回计数器的值。
在main函数中,调用countRecursive函数并传入取消条件,然后将返回值作为main函数的返回值。
通过以上的解决方法,实现了函数参数只能由函数自身写入的要求,确保了计数器的正确性和一致性。
问题的出现原因:在给定的代码中,函数`countRecursive`需要一个递归计数器作为参数,但是这个计数器参数可以被外部代码修改,从而导致函数的递归计数出现错误。
解决方法:将函数`countRecursive`包装在一个本地类的静态成员函数中,通过这种方式可以实现对计数器参数的封装,使其只能被函数本身修改。
具体的解决方法如下所示:
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++中的本地类(local class)的特性,本地类拥有一些限制,但是可以拥有静态成员函数。通过将`countRecursive`函数作为`hidden`类的静态成员函数,外部代码无法直接修改`counter`参数,从而保证了计数器参数的可写性只限于函数本身。
作者对这个解决方法表示赞同,并认为这是一个对于问题非常直接的解决方法,特别适用于内联函数,因为内部函数更难隐藏。
其他参与讨论的答案也被认为具有一定的价值和思考,但是这个解决方法被认为是最直接且有效的,非常感谢大家的帮助和意见。
通过将函数包装在本地类的静态成员函数中,可以实现对函数参数的封装,使其只能被函数本身修改,从而解决了函数参数可写性的问题。这种方法在C++中很少见,但是非常实用。