我正在查看以下代码:
string toUpper(string s) {
string result;
int (*toupperp)(int) = &toupper; // toupper is overloaded
transform(begin(s), end(s), back_inserter(result), toupperp);
return result;
}
我对这一行感到困惑:
int (*toupperp)(int) = &toupper; // toupper is overloaded
1.为什么这条线是必要的?
2.我相信&
从内存中检索指向某事物的指针。但toupper
,函数的名称已经是指针,不是吗?为什么我们不能这样做:
int (*toupperp)(int) = toupper;
3.如果函数在int
上使用,为什么会重载到string
?
答案 0 :(得分:5)
1)真的没有必要。如果您使用了using namespace std
指令,则必须将所需类型转换为let the compiler know which overload you want。所以,你也可以说
transform(begin(s), end(s), back_inserter(result), static_cast<int(*)(int)>(&toupper));
否则以下内容应该足够了:
transform(begin(s), end(s), back_inserter(result), ::toupper);
2)作为函数名称的标识符会衰减为指针,是的,但它们并不完全相同。话虽如此,在这种情况下应该没问题
int (*toupperp)(int) = toupper;
甚至(如果您还没有使用using namespace std
指令):
auto toupperp = toupper;
3)它与C标准库的兼容性。它用于s
的每个元素,string
为char
。
答案 1 :(得分:4)
您传递给transform
的内容是指向函数toupper
的指针(请参阅function pointers)。将此指针存储到局部变量toupperp
中。 toupperp
的类型是指向以int
为参数并返回int
的函数的指针。
除非以奇怪的方式定义toupper
,否则transform
似乎使用该函数将每个输入字符更改为大写。每个单个字符都被处理为一个整数(如果需要,可以使用隐式转换)。
关于你的问题2,使用运算符&
你更明确地表示你正在使用函数的地址,但实际上你可以省略它。见here(我今天学到了一些东西)。
如果toupper
过载,使用中间变量是获得所需过载的安全方法。如果所需的重载消失,则此方法将在编译时捕获该问题。见here。 (这是我今天学到的其他东西)。