我试图创建一个指向具有默认参数的成员函数的指针.当我通过这个函数指针调用时,我不想为默认参数指定一个参数.根据标准,这是不允许的,但我从来没有发现任何标准不允许的东西,我不能以其他一致的方式做.到目前为止,我还没有找到办法做到这一点.
这是代码,说明我正在尝试解决的问题:
class MyObj
{
public:
int foo(const char* val) { return 1; }
int bar(int val = 42) { return 2; }
};
int main()
{
MyObj o;
typedef int(MyObj::*fooptr)(const char*);
fooptr fp = &MyObj::foo;
int r1 = (o.*fp)("Hello, foo.");
typedef int(MyObj::*barptr)(int);
barptr bp1 = &MyObj::bar;
int r2 = (o.*bp1)(); // <-- ERROR: too few arguments for call
typedef int (MyObj::*barptr2)();
barptr2 bp2 = &MyObj::bar; // <-- ERROR: Can't convert from int(MyObj::*)(int) to int(MyObj::*)(void)
int r3 = (o.*bp2)();
return 0;
}
Run Code Online (Sandbox Code Playgroud)
如果我不想为默认参数指定任何值,有关如何在符合C++中执行此操作的任何想法?
编辑:稍微澄清一下限制.我不想在调用或任何typedef中指定任何默认参数.例如,我不想这样做:
typedef int(MyObj::*barptr)(int = 5);
Run Code Online (Sandbox Code Playgroud)
...我也不想这样做:
typedef int(MyObj::*barptr)(int);
...
(o.barptr)(5);
Run Code Online (Sandbox Code Playgroud)
AnT*_*AnT 17
期望函数指针以您期望它们在您的示例中工作的方式工作将是相当奇怪的."默认参数"是纯粹的编译时概念,它是一种语法糖.尽管在函数声明或定义中指定了默认参数,但它们实际上与函数本身无关.实际上,默认参数在调用时被替换,即它们在调用者的上下文中处理.从函数的角度来看,用户提供的显式参数或编译器隐式提供的默认参数之间没有区别.
另一方面,函数指针是运行时实体.它们在运行时初始化.在运行时默认参数根本不存在.在C++中没有"运行时默认参数"这样的概念.
有些编译器允许您在函数指针声明中指定默认参数,如
void foo(int);
int main() {
void (*pfoo)(int = 42) = foo;
pfoo(); // same as 'pfoo(42)'
}
Run Code Online (Sandbox Code Playgroud)
但这不是标准的C++,这似乎不是你想要的,因为你希望"默认参数"值在运行时根据指针指向的函数而改变.
只要你想与真正的函数指针,坚持(而不是函数对象,又名函子)立即解决办法是为你提供你的函数的参数少版本以不同的名称,如
class MyObj
{
public:
...
int bar(int val = 42) { return 2; }
int bar_default() { return bar(); }
};
int main()
{
MyObj o;
typedef int (MyObj::*barptr2)();
barptr2 bp2 = &MyObj::bar_default;
int r3 = (o.*bp2)();
return 0;
}
Run Code Online (Sandbox Code Playgroud)
当然,这远非优雅.
实际上,人们可以争辩说,我在上面bar_default所做的事情可能是由编译器隐式完成的,作为一种语言特性.例如,给出了类定义
class MyObj
{
public:
...
int bar(int val = 42) { return 2; }
...
};
Run Code Online (Sandbox Code Playgroud)
人们可能希望编译器允许以下内容
int main()
{
MyObj o;
typedef int (MyObj::*barptr2)();
barptr2 bp2 = &MyObj::bar;
int r3 = (o.*bp2)();
return 0;
}
Run Code Online (Sandbox Code Playgroud)
指针初始化实际上会强制编译器隐式生成"适配器"函数MyObj::bar(与bar_default我之前的示例相同),并设置bp2为指向该适配器.但是,目前C++语言中没有这样的功能.引入类似的东西需要比第一眼看上去更多的努力.
另请注意,在最后两个示例中,指针类型int (MyObj::*)()是不同的int (MyObj::*)(int).这实际上是一个问题(因为你在你的例子中尝试了两个):你希望它如何工作?用int (MyObj::*)()指针?还是用int (MyObj::*)(int)指针?