我正在学习一个教程系列,其中有一个关于回调函数的课程,其中包含一个简单的计算器。我不擅长编程,但我了解指针和函数。
本教程演示了一个简单的案例,其中有两个接受 (int, int) 的函数和一个接受函数指针作为参数的函数,但我决定对其进行自己的改造,并传递一个 double 数组和两个 size_t 变量(以标记数组的开头和结尾)作为加法和减法函数的参数。
我尝试将三个参数传递给所有函数,并将一个函数指针传递给“操作”函数。 我希望程序根据用户的选择添加或减去数组中的所有数字。
#include <iostream>
#include <cmath>
double add(double[], size_t, size_t);
double subtract(double[], size_t, size_t);
int main()
{
double numbers[] { 1.3, 2.0, 3.5};
size_t start = 0;
size_t end = std::size(numbers);
double(*operation)(double(*), double numbers[], size_t start, size_t end); // a function pointer
char choice = '0'; // a char variable for the choice of operation
double result; // result of the operation for the output
std::cin >> choice; // input
if(choice == '+')
{
result = operation(add, numbers, &start, &end); // passing the addition function as an argument to the operation function
}
if(choice == '-')
{
result = operation(subtract, numbers, &start, &end);
}
std::cout << result << std::endl; // output
}
double add(double numbers[], size_t *start, size_t *end) // add all numbers in the array
{
double result = 0;
for(int i = *start; i < *end; i++)
{
result += numbers[i];
}
return result;
}
double subtract(double numbers[], size_t start, size_t end) // subtract the following numbers from the first one in the array
{
double result = 0;
for(int i = start; i < end; i++)
{
result -= numbers[i];
}
return result;
}
double operation(double(*op)(double, size_t, size_t), double numbers[], size_t start, size_t end)
{
return op(numbers, start, end); // the function that accepts two functions as arguments
}
我从编译器得到的错误是:
funcpointerscalc.cpp: In function ‘int main()’:
funcpointerscalc.cpp:20:28: error: cannot convert ‘double (*)(double*, size_t, size_t)’ {aka ‘double (*)(double*, long unsigned int, long unsigned int)’} to ‘double*’ in argument passing
20 | result = operation(add, numbers, &start, &end);
| ^~~
| |
| double (*)(double*, size_t, size_t) {aka double (*)(double*, long unsigned int, long unsigned int)}
funcpointerscalc.cpp:24:28: error: cannot convert ‘double (*)(double*, size_t, size_t)’ {aka ‘double (*)(double*, long unsigned int, long unsigned int)’} to ‘double*’ in argument passing
24 | result = operation(subtract, numbers, &start, &end);
| ^~~~~~~~
| |
| double (*)(double*, size_t, size_t) {aka double (*)(double*, long unsigned int, long unsigned int)}
funcpointerscalc.cpp: In function ‘double* add(double*, size_t*, size_t*)’:
funcpointerscalc.cpp:37:12: error: invalid type argument of unary ‘*’ (have ‘double’)
37 | return *result;
| ^~~~~~~
funcpointerscalc.cpp: At global scope:
funcpointerscalc.cpp:40:9: error: ambiguating new declaration of ‘double* subtract(double*, size_t, size_t)’
40 | double* subtract(double numbers[], size_t start, size_t end)
| ^~~~~~~~
funcpointerscalc.cpp:5:8: note: old declaration ‘double subtract(double*, size_t, size_t)’
5 | double subtract(double[], size_t, size_t);
| ^~~~~~~~
funcpointerscalc.cpp: In function ‘double* subtract(double*, size_t, size_t)’:
funcpointerscalc.cpp:48:12: error: invalid type argument of unary ‘*’ (have ‘double’)
48 | return *result;
| ^~~~~~~
funcpointerscalc.cpp: In function ‘double operation(double (*)(double, size_t, size_t), double*, size_t, size_t)’:
funcpointerscalc.cpp:53:15: error: cannot convert ‘double*’ to ‘double’ in argument passing
53 | return op(numbers, start, end);
| ^~~~~~~
| |
| double*
您的代码中存在一些问题。
这里
double(*operation)(double(*), double numbers[], size_t start, size_t end); // a function pointer
您声明了一个名为
operation
的函数指针。这会影响调用名为 operation
的函数的方式。您现在得到的错误抱怨 add
不是 double*
,因为这就是 operation
的声明方式:第一个参数是 double*
的函数指针。
删除函数指针的声明。现在,您将看到您尝试在声明函数之前调用该函数:https://godbolt.org/z/YsMfqM4ee。
像对
add
和 subtract
那样预先声明函数。您现在将看到错误,因为功能点的签名错误:
double operation(double(*op)(double, size_t, size_t), double numbers[], size_t start, size_t end)
此函数需要一个函数指针作为第一个参数,该函数指针以
double
作为第一个参数。你的 add
和减法得到 double*
。
接下来,您的一个函数将
start
和 end
作为另一个按值的指针。那是行不通的。坚持一个。我将按值传递它们,因此:
错误:
result = operation(add, numbers, &start, &end);
正确:
result = operation(add, numbers, start, end);
并相应地调整函数签名。
这就是使您的代码编译的原因:https://godbolt.org/z/3jMPE43Ed。它在语法上是正确的。您现在应该编写测试来查看它是否执行了预期的操作。对于测试不要依赖
std::cin
。对于频繁的测试并且您想要可重复的运行来说太不方便了。在代码中编写示例,您可以直接比较预期结果和实际结果。