gpt4 book ai didi

c++ - 将数学函数作为方法的输入参数传递给C++

转载 作者:行者123 更新时间:2023-11-30 02:23:31 25 4
gpt4 key购买 nike

我正在尝试编写一个通用的积分函数,我想以一种可以接受任何数学函数的方式来实现它。也就是说,我想将数学函数作为输入参数传递。用伪代码:simpson_int(x*x)。我听说过function中的<functional>模板,但是我对C++中的模板没有真正的经验。

最佳答案

我想到了一些解决方案(这是我要解决的问题的方法,以确保还有更多解决方案,也许我要指出的不是最好的),请考虑以下事实:参数函数在Simpson实现中不止一次(因此,您需要一个“callable”参数):

功能指针

函数指针(比C++更多的C语言),在其中使用两个参数进行声明:第一个是具有指定类型的函数的指针,而第二个是函数的参数。让我们
举个例子:

#include <iostream>

double power2(double x) {
return x * x;
}

double simspon(double (*f)(double), double x) {
return f(x);
}

int main() {
std::cout << simspon(power2, 2);
return 0;
}

在这种情况下,我没有使用模板来达到结果。但这将 而不是接受任何函数作为第一个参数,而是仅将参数作为 double 值并返回 double 值的函数。

我认为大多数C++程序员都会建议您避免这种方法。

函数指针和模板

因此,您可能想使用模板扩展前面的示例,并使其更通用。重新定义功能非常简单
接受仅在代码中使用模板时才实际指定的模板(抽象类型):
#include <iostream>

double power2(double x) {
return x * x;
}

int power2int(int x) {
return x * x;
}

template <class T, class P>
P simspon(T (*f)(P), P x) {
return f(x);
}

int main() {
std::cout << simspon<double, double>(power2, 2.0);
std::cout << simspon<int, int>(power2int, 2);
return 0;
}
TP是两个模板:第一个用于描述函数指针的返回值,第二个用于指定函数指针的参数,以及 simpson的返回值,因此在编写 template <class T, classP>时实际上是在通知您正在使用T和P作为不同类型的占位符的编译器。当您在 main中调用该函数时,实际上您将在以后声明所需的类型。 这不是很好的代码,但是我正在构建理解模板的路径。同样, 可以在您实际使用simpson调用< >时指定参数函数的类型。

( 免责声明:,您应该考虑使用 template <typename T ...>代替类。但是我与旧的 class一起使用,并且在某些情况下无法使用 typename,因此有很多关于SO的问题都涉及到此。)

使用 std::function
可能不希望使用函数指针作为参数,而希望创建一个变量,该变量存储要作为 simpson的参数传递的函数。这带来了几个优点,因为它们实际上是代码内的对象,在某些不需要的情况下具有某些可预测的行为(例如,对于空函数指针,则必须检查指针本身并进行处理,对于 std::function,如果没有可调用的指针,它会引发 std::bad_function_call错误)

这是一个示例,它像以前一样再次使用模板:
#include <iostream>
#include <functional>

double power2(double x) {
return x * x;
}

int power2int(int x) {
return x * x;
}

template <class T, class P>
P simspon(std::function<T(P)> f, P x) {
return f(x);
}

int main() {
std::function<double(double)> p_power2 = power2;
std::cout << simspon<double, double>(p_power2, 2.0);

std::function<double(double)> p_power2int = power2int;
std::cout << simspon<int, int>(power2int, 2);
return 0;
}

使用lambdas

lambda是闭包,在您的情况下(如果可以使用标准C++ 14)可以与 auto关键字一起使用,以实现相当普遍的行为,而无需显式使用模板。闭包还能够捕获部分/整个上下文 check the reference

让我们看一个示例,在该示例中,我创建了两个分别接收不同参数的lambda和一个非常通用的 simpson函数(实际上不是,编译器针对您执行的调用定义了不同的函数)。
#include <iostream>

auto lambda = [](auto x) { return x * x ; };
auto lambda_2 = [] (int x) { return x + 10; };

auto simpson(auto f, auto x) {
return f(x);
}

int main() {
std::cout << simpson(lambda, 2.0);
std::cout << simpson(lambda_2, 1);
return 0;
}

您需要使用 -std=c++14标志进行编译。我想到了无数的建议,建议您避免以这种方式实现代码,请记住,它仅用于说明目的(我用 auto关键字进行了更多夸张)。

函数对象(问题类)

也许对您的情况有所改进,就是为数学函数编写一个通用类,以集成对象并将其传递给函数。这带来了许多优点:您可能希望将一些集成结果保存在函数内部,甚至编写流运算符以漂亮地打印问题。这是数学库通常采用的解决方案。

在这种极其简单的情况下,我们有一个问题类。当您为此类创建新实例时, std::function将传递给构造函数并存储在该类内部。该类的实例是 simpson的参数:
#include <iostream>
#include <functional>

template <class T, class P>
class Problem {
public:
// Attributes
std::function<T(P)> _f;

// Constructor
Problem(std::function<T(P)> f) : _f(f) {};

// Making the object callable
P operator()(P x) { return _f(x); }
};

template <class T, class P>
P simspon(Problem<T, P> p, P x) {
return p(x);
}

int main() {
Problem<double, double> prb([](double x) { return x * x; });
std::cout << simspon<double, double>(prb, 2);
return 0;
}

关于c++ - 将数学函数作为方法的输入参数传递给C++,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46133818/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com