默认参数和函数指针作为函数参数C++
Default parameter and function pointer as function arguments C++
我有一个函数,它接受参数,默认参数,最后,一个指向另一个函数的指针和一个空指针。
例如,请考虑以下内容
int foo(double arg 1, bool arg 2, int arg3=0, int arg4=2, bool (*pbar)(bool,void*), void* data=0);
在我的代码库中的几个地方调用了它。我注意到,当函数指针本身有参数时,然后是默认参数,即使我想要的值是默认参数,也必须指定默认参数。例如,以下代码将编译
foo(arg1, arg2, pbar);
但下面的代码片段不会
foo(arg1, arg2, pbar, (void*) myint);
作为一个更完整的示例,下面是一个工作片段。
#include <iostream>
using namespace std;
int foo(double arg1, bool arg2, int arg3=0, int arg4=2, bool (*pbar)(bool,void*)=0, void* data=0)
{
return 1;
}
bool bar(bool bt, void* vs)
{
return false;
}
int main()
{
double arg1 = 0.0;
bool arg2 = false;
bool bt = true;
int i = 1;
void* vs = &i;
bool pbar = bar(bt, vs);
// no defaults specified and no function pointer arguments
foo(arg1, arg2, pbar);
// specify one of the defaults
int arg3 = 23;
foo(arg1, arg2, arg3, pbar);
// don't specify the defaults, but give arguments to function pointer
//foo(arg1, arg2, pbar, bt, vs);
return 0;
}
最终注释的调用将不会编译。
所以我的问题是,为什么在函数指针参数的规范下无法编译?
我已经通过使用"命名参数"方法找到了解决问题的方法。借此我创建一个类并使用引用实例化成员。但是,我对上述失败的原因进行深入解释感兴趣。
错误如下所示
main.cpp: In function ‘int main()’:
main.cpp:41:33: error: invalid conversion from ‘void*’ to ‘bool (*)(bool, void*)’ [-fpermissive]
foo(arg1, arg2, pbar, bt, vs);
^
main.cpp:13:5: note: initializing argument 5 of ‘int foo(double, bool, int, int, bool (*)(bool, void*), void*)’
int foo(double arg1, bool arg2, int arg3=0, int arg4=2, bool (*pbar)(bool,void*)=0, void* data=0)
^~~
我相信这是因为参数的顺序搞砸了。但是,为什么我可以插入函数指针而不担心默认的 arg3 和 arg4?
int foo(double arg1, bool arg2, int arg3 = 0, int arg4 = 2, bool * pbar(bool , void *) = 0, void * data = 0);
编译器只关心参数的顺序。
不能跳过定义 arg3 和 arg4,因为它们具有默认值。
通过这样做:
foo(arg1, arg2, pbar);
你基本上是在传递"pbar"(这是一个函数(,其中"arg3"应该是(这是一个整数(
所以我的问题是,为什么在函数指针参数的规范下无法编译?
它无法编译您传递的参数具有错误的类型。参数的类型是指向函数的指针。您正在传递一个void*
,这是一个对象指针。void*
不能隐式转换为指向函数的指针。
int foo( double arg1, bool arg2, int arg3=0, int arg4=2, bool (*pbar)(bool,void*)=0, void* data=0) 1 2 3 4 ^^^^^^^^^ 5 ^^^^^^^^^^^^ pointer to function void* vs = &i; ^^^^^ not a pointer to function foo(arg1, arg2, pbar, bt, vs); 1 2 3 4 ^5
参数仍然必须按正确的顺序排列。然后,您可以选择要包含的可选参数数量,但请注意,不能跳过任何可选参数。
所以在你的例子中,foo(arg1, arg2, pbar(工作是因为pbar不是一个函数,它只是一个布尔值。 bar(( 返回 false,因此 pbar 将被设置为 0,然后在执行 foo(arg1, arg2, pbar( 时将其转换为整数,因为第三个参数是整数,所以这就是它工作的原因。
与第二个调用 foo(arg1, arg2, arg3, pbar 相同(,pbar 仍然只有 0。
注释的调用返回错误,因为如前所述,您无法跳过可选参数,因此 foo(arg1, arg2, pbar, bt, vs( 将传入 vs(一个 void 指针(作为函数指针。如果要包含特定的可选参数,则必须在该参数之前指定所有参数。
默认参数背后的基本原则是它们适用于参数列表中最右侧的参数。
void f(int, double = 0, void* = 0); // okay
void g(int, double = 0, void*); // error: third argument needs a default value
同样,当使用默认参数调用函数时,只有最右侧的参数获取其默认值:
f(3); // okay; second and third arguments get default values
f(3, 1.0); // okay; third argument gets default value
int x;
f(3, 1.0, &x); // okay; no default arguments used
你不能跳过参数,即使可以确定你的意思是哪一个:
f(3, &x); // illegal: second argument has type double, and &x can't be converted to double
如果其中一个参数可转换为适当的类型,这可能会令人困惑,并且看起来这可能是编译问题中的代码中发生的情况。例如
void h(int, bool = false, int* = 0);
int x;
h(3, &x); // okay; &x gets converted to bool
h(3, true); // same as the previous one
h(3, false, &x); // okay, all three arguments provided
- 将可变参数函数的参数封装在类实例中
- QML 使用带有参数C++函数
- 使用可变参数函数作为模板参数
- 如何在C++中伪造虚拟可变参数函数模板?
- 为什么可变参数函数不适用于模板
- C++ std::functional 中的可变参数函数模板
- 可变参数函数指针的定义对于VxWorks spyLib来说不清楚
- 使用可变参数函数覆盖具有不同函数签名的虚函数
- 考虑引用和常量的可变参数函数包装器
- 使用可变参数函数将整数和/或整数数组放入单个 int 数组中
- 在可变参数函数中转发特定范围的参数
- 通过引用传递参数;函数返回类型是否必须为 VOID?
- 使用带有一个参数函数的递归找到数字的平方
- 可变参数函数模板不能很好地使用 std::function 作为参数
- 多个可变参数函数的单个模板参数包?
- 参数数据类型未知的可变参数函数
- 可变参数函数参数包扩展
- 使用模板可变参数函数将多个参数传递给另一个函数
- 对可变参数函数的递归调用的链接器错误
- 通过像printf这样的可变参数函数传递一个带有常量字符*转换函数的类