章节目录

函数的delete说明符

本节阅读量:

在某些情况下,编写的函数,不希望被某些类型的参数来调用。

考虑以下示例:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
#include <iostream>

void printInt(int x)
{
    std::cout << x << '\n';
}

int main()
{
    printInt(5);    // okay: 打印 5
    printInt('a');  // 打印 97 -- 这样的输出是否有意义?
    printInt(true); // 打印 1 -- 这样的输出是否有意义?
    
    return 0;
}

此示例打印:

1
2
3
5
97
1

虽然printInt(5)显然没问题,但对printInt()的其他两个调用值得怀疑。使用printInt(‘a’),编译器将确定它可以将’a’提升为int值97,以便将函数调用与函数定义相匹配。同理将把true提升为int值1。

假设我们认为用char或bool类型的值调用printInt()没有意义。我们能做什么?


使用=delete说明符删除函数

在我们有一个显式不希望可调用的函数的情况下,可以使用=delete说明符将该函数定义为删除。如果编译器将函数调用与已删除函数相匹配,则将因编译错误而停止编译。

下面是使用此语法的上述更新版本:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
#include <iostream>

void printInt(int x)
{
    std::cout << x << '\n';
}

void printInt(char) = delete; // 编译时匹配到这个函数将报错
void printInt(bool) = delete; // 编译时匹配到这个函数将报错

int main()
{
    printInt(97);   // okay

    printInt('a');  // 编译失败: 匹配到的函数被删除
    printInt(true); // 编译失败: 匹配到的函数被删除

    printInt(5.0);  // 编译失败: 有多个可匹配的函数
    
    return 0;
}

让我们快速看一下。首先,printInt(‘a’)与printInt(char)精确匹配,该函数被删除。编译器因此产生编译错误。printInt(true)与printInt(bool)精确匹配,该函数被删除,因此也会产生编译错误。

printInt(5.0)是一个有趣的例子,可能会产生意想不到的结果。首先,编译器检查是否存在完全匹配的printInt(double)。没有找到。接下来,编译器尝试查找最佳匹配。尽管printInt(int)是唯一未删除的函数,但已删除的函数仍然被视为函数重载决议的候选函数。由于这些函数都不是明确的最佳匹配,编译器将发出不明确匹配的编译错误。


删除所有不匹配的重载

删除一组单独的函数重载可以很好地工作,但可能会很冗长。有时,我们可能希望仅使用类型与函数参数完全匹配的值来调用某个函数。我们可以通过使用函数模板(在即将到来的函数模板中介绍)来实现这一点,如下所示:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
#include <iostream>

// 这个函数优先使用int参数来匹配
void printInt(int x)
{
    std::cout << x << '\n';
}

// 这个函数模版将会匹配其它所有类型
// 因为这个函数模版被删除,因此匹配到它,将会导致编译失败
template <typename T>
void printInt(T x) = delete;

int main()
{
    printInt(97);   // okay
    printInt('a');  // 编译报错
    printInt(true); // 编译报错
    
    return 0;
}

11.2 函数重载决议

上一节

11.4 默认参数

下一节