这听起来有点令人费解,但我们走了。
所以,我有以下代码:
void Utility::validateRangeAndModify(Pet pet, int checkint,
int numbertovalidate,
bool greaterorless)
{
if (greaterorless) {
if (numbertovalidate < checkint)
pet.getAttributes()->setPetHunger(0);
} else
if (numbertovalidate > checkint)
pet.getAttributes()->func(100);
}
首先,此代码旨在验证单个整数。那部分很容易。
然后,我想要它做的是执行 a 函数,具体取决于整数是否满足条件。在这种情况下,setPetHunger()
被设置为0或100.问题是,我也有setPetHealth()
和setPetEnergy()
。
我希望它执行的功能是我想要改变的事情。
例如。 此代码仅适用于我的宠物饥饿。 它不会起作用因为它的健康,幸福或任何其他变量。我还有很多其他的变数。
我想知道是否有办法实现这样的目标:
void Utility::validateRangeAndModify(Pet pet,
int checkint,
int numbertovalidate,
bool greaterorless,
string functiontouse)
{
if (greaterorless) {
if (numbertovalidate < checkint)
pet.getAttributes()->setPetHunger(0);
} else
if (numbertovalidate > checkint)
pet.getAttributes()->FUNCTION_TO_USE(100);
}
我可以在C#中使用类似反射的东西。但是,我不知道c ++中的替代函数
答案 0 :(得分:1)
您可以将正确的成员函数指针作为参数传递给Utility::validateRangeAndModify
,如下所示:
void
Utility::validateRangeAndModify(Pet &pet, int checkint, int numbertovalidate,
bool greaterorless, void(Attrib::*memfun)(int)) {
^^^^^^^^^^^^^^^^^^^^^^^^^^
if(greaterorless) {
if(numbertovalidate < checkint) (pet.getAttributes()->*memfun)(0);
} else {
if(numbertovalidate < checkint) (pet.getAttributes()->*memfun)(100);
}
}
然后将其称为(如果Utility::validateRangeAndModify
不是static
使用obj.validateRangeAndModify
):
Utility::validateRangeAndModify(p, 10, 9, false, &Attrib::setPetHunger);
Utility::validateRangeAndModify(p, 10, 9, false, &Attrib::setPetThirst);
答案 1 :(得分:0)
您应该使用函数指针:
void Utility::validateRangeAndModify(Pet pet, int checkint,
int numbertovalidate,
bool greaterorless,
void (*func)(int, attribs &))
{
if (greaterorless) {
if (numbertovalidate < checkint)
pet.getAttributes()->setPetHunger(0);
} else
if (numbertovalidate > checkint)
func(100, pet.getAttribs());
}
您和客户将同意您将通过的功能原型;在这种情况下,原型将是void func(int, attribs &);
客户端可以编写如下代码:
void happiness(int level, attribs &a)
{
// some code here
}
Utility::validateRangeAndModify(..., happiness);
现在happiness
函数会调用validateRangeAndModify
。
注意:happiness
是一个免费功能。如果它是成员函数,请将其标记为static
:那么就不会有额外的this
参数。
答案 2 :(得分:0)
为了简单起见,我提供了一个非常简单的程序,它使用std::bind,std::function和std::placeholders来允许调用绑定方法。这样可以使用该方法保持正确的this
,并且通常可以防止恶意。
#include <iostream>
#include <functional>
// bait class to catch bound function calls. Replace this with pet for OP's example
class TwoMethods
{
public:
void method1(int val)
{
std::cout << "Method 1 received " << val << std::endl;
}
void method2(int val)
{
std::cout << "Method 2 received " << val << std::endl;
}
};
// utility function that will operate on a bound function
void utilityfunction(std::function<void(int)> func)
{
// calls passed function. Quietly handles bound this parameter and replaces
// placeholder with 42
func(42);
}
int main()
{
TwoMethods obj;
// call utility function with appropriate object and method
// the std::placeholders::_1 lets the compiler know there is another parameter that
// will be supplied later
utilityfunction(std::bind(&TwoMethods::method1, obj, std::placeholders::_1));
utilityfunction(std::bind(&TwoMethods::method2, obj, std::placeholders::_1));
}
在OP的案例中:
void Utility::validateRangeAndModify(int checkint,
int numbertovalidate,
bool greaterorless,
std::function<void(int)> func)
{
switch (greaterorless)
{
case 0:
{
if (numbertovalidate < checkint)
{
func(0);
}
}
break;
case 1:
{
if (numbertovalidate > checkint)
{
func(100);
}
break;
}
}
}
并称之为:
validateRangeAndModify(42, 666, false,
std::bind(&Attributes::setPetHunger,
pet.getAttributes(),
std::placeholders::_1))