11-4 删除函数
在某些情况下,可能编写出在调用特定类型值时行为异常的函数。
请看以下示例:
#include <iostream>
void printInt(int x)
{
std::cout << x << '\n';
}
int main()
{
printInt(5); // okay: prints 5
printInt('a'); // prints 97 -- does this make sense?
printInt(true); // print 1 -- does this make sense?
return 0;
}
该示例输出:

虽然 printInt(5) 显然正常,但另外两次 printInt() 调用则值得商榷。对于 printInt(‘a’),编译器会判断可将 ‘a’ 提升为 int 值 97 以匹配函数调用与定义。同时将 true 提升为 int 值 1,且不会报错。
假设我们认为用 char 或 bool 类型调用 printInt() 毫无意义,该如何处理?
使用 = delete 限定符删除函数
当明确需要禁用函数调用时,可通过 = delete 限定符将该函数标记为已删除。若编译器发现函数调用指向已删除的函数,编译过程将因编译错误而终止。
以下是采用此语法的更新版本:
#include <iostream>
void printInt(int x)
{
std::cout << x << '\n';
}
void printInt(char) = delete; // calls to this function will halt compilation
void printInt(bool) = delete; // calls to this function will halt compilation
int main()
{
printInt(97); // okay
printInt('a'); // compile error: function deleted
printInt(true); // compile error: function deleted
printInt(5.0); // compile error: ambiguous match
return 0;
}

我们快速分析几个示例:首先,printInt(‘a’) 与被删除的 printInt(char) 直接匹配,因此编译器报错。printInt(true) 与被删除的 printInt(bool) 直接匹配,同样导致编译错误。
printInt(5.0) 是个有趣的案例,结果可能出乎意料。编译器首先检查是否存在精确匹配的 printInt(double),未找到。接着尝试寻找最佳匹配。尽管 printInt(int) 是唯一未被删除的函数,但在函数重载解析中仍会考虑已删除函数作为候选项。由于所有函数均无法明确确定最佳匹配,编译器将报出模糊匹配编译错误。
关键要点
= delete 表示“我禁止此项”,而非“此项不存在”。
删除函数参与函数重载解析的所有阶段(不仅限于精确匹配阶段)。若被选中的函数已被删除,则导致编译错误。
对于进阶读者
其他类型的函数也可采用类似方式删除。
第14.14节——复制构造函数介绍将讨论删除成员函数,第11.7节——函数模板实例化 将探讨删除函数模板特化。
删除所有不匹配的重载函数(进阶)
逐个删除函数重载虽可行,但可能冗长。有时我们希望特定函数仅接受与实参类型完全匹配的形参。可通过函数模板(详见后续第11.6节——函数模板)实现如下:
#include <iostream>
// This function will take precedence for arguments of type int
void printInt(int x)
{
std::cout << x << '\n';
}
// This function template will take precedence for arguments of other types
// Since this function template is deleted, calls to it will halt compilation
template <typename T>
void printInt(T x) = delete;
int main()
{
printInt(97); // okay
printInt('a'); // compile error
printInt(true); // compile error
return 0;
}


浙公网安备 33010602011771号