怎么理解 C++ 的 explicit 关键字?

简介: 给构造函数声明 explicit 可以阻止它们被用来执行隐式类型转换(implicit type conversions)。本文通过一个例子来直观地帮助大家理解 C++ 中的 explicit 关键字。

给构造函数声明 explicit 可以阻止它们被用来执行隐式类型转换(implicit type conversions),例如对于下面的代码:

using namespace std;

class Student {
public:
    int id, score;
    Student(int id = 0, int score = 0) : id(id), score(score) {}
};

void display(Student s) {
    cout << "ID: " << s.id 
         << ", Score: " << s.score << endl;
}

int main() {
    display(1);
    Student s = 1;
    cout << "ID: " << s.id 
         << ", Score: " << s.score << endl;
    return 0;
}

我们定义了一个 Student 类,然后构造函数没有用 scplicit 声明,该类有两个变量,分别是学生的学号 id 和分数 score,并且都有默认值 0. 还定义了一个函数 display 来打印出 Student 类的两个变量。

main 函数中我们调用 display(1),按照函数的定义,应该是传入一个 Student 类的,但是现在是传入一个整数 1,按道理应该不是正确的用法,正确的用法应该是 display(Student(1))。对于 Student s = 1; 直接将整数 1 赋值给一个 Student 类,按道理也应该是不正确,正确的应该是 Student s(1)

但是这个代码可以编译并且成功运行,并且输出:ID: 1, Score: 0

这就是发生了隐式类型转换。如果给构造函数前面加上 explicit 关键字声明,类定义变成:

using namespace std;

class Student {
public:
    int id, score;
    explicit Student(int id = 0, int score = 0) : id(id), score(score) {}
};

其他的不变,只是第 6 行加了一个 explicit,那么就会编译不通过。因为这个时候就无法进行隐式类型转换。

main 函数重新写成这样:

int main() {
    display(Student(1));
    Student s(1);
    cout << "ID: " << s.id
         << ", Score: " << s.score << endl;
    return 0;
}

就可以编译通过正常执行,并且输出:ID: 1, Score: 0

目录
相关文章
|
存储 编译器 程序员
c++的类(附含explicit关键字,友元,内部类)
本文介绍了C++中类的核心概念与用法,涵盖封装、继承、多态三大特性。重点讲解了类的定义(`class`与`struct`)、访问限定符(`private`、`public`、`protected`)、类的作用域及成员函数的声明与定义分离。同时深入探讨了类的大小计算、`this`指针、默认成员函数(构造函数、析构函数、拷贝构造、赋值重载)以及运算符重载等内容。 文章还详细分析了`explicit`关键字的作用、静态成员(变量与函数)、友元(友元函数与友元类)的概念及其使用场景,并简要介绍了内部类的特性。
523 0
|
安全 编译器 程序员
C++ noexcept 关键字的关键作用
`noexcept` 关键字在 C++ 中扮演着重要角色,通过正确使用 `noexcept`,可以提升程序的性能、增强代码的可读性和安全性,并且有助于编译器进行优化。在编写 C++ 代码时,应仔细考虑每个函数是否应该声明为 `noexcept`,以充分利用这一特性带来的优势。通过本文的介绍,希望开发者能够更好地理解和应用 `noexcept` 关键字,从而编写出更加高效、健壮的 C++ 程序。
570 8
|
安全 编译器 C++
C++ `noexcept` 关键字的深入解析
`noexcept` 关键字在 C++ 中用于指示函数不会抛出异常,有助于编译器优化和提高程序的可靠性。它可以减少代码大小、提高执行效率,并增强程序的稳定性和可预测性。`noexcept` 还可以影响函数重载和模板特化的决策。使用时需谨慎,确保函数确实不会抛出异常,否则可能导致程序崩溃。通过合理使用 `noexcept`,开发者可以编写出更高效、更可靠的 C++ 代码。
|
存储 安全 编译器
【C++】C++特性揭秘:引用与内联函数 | auto关键字与for循环 | 指针空值(一)
【C++】C++特性揭秘:引用与内联函数 | auto关键字与for循环 | 指针空值
344 1
|
存储 安全 编译器
C++入门 | auto关键字、范围for、指针空值nullptr
C++入门 | auto关键字、范围for、指针空值nullptr
487 4
|
存储 安全 编译器
【C++入门 四】学习C++内联函数 | auto关键字 | 基于范围的for循环(C++11) | 指针空值nullptr(C++11)
【C++入门 四】学习C++内联函数 | auto关键字 | 基于范围的for循环(C++11) | 指针空值nullptr(C++11)
|
存储 编译器 程序员
【C++】C++特性揭秘:引用与内联函数 | auto关键字与for循环 | 指针空值(二)
【C++】C++特性揭秘:引用与内联函数 | auto关键字与for循环 | 指针空值
266 0
|
存储 安全 编译器
【C++航海王:追寻罗杰的编程之路】引用、内联、auto关键字、基于范围的for、指针空值nullptr
【C++航海王:追寻罗杰的编程之路】引用、内联、auto关键字、基于范围的for、指针空值nullptr
315 5
|
存储 编译器 程序员
C++一分钟之-auto关键字与类型推导
【6月更文挑战第21天】`auto`在C++11中重生,简化了类型声明,尤其在处理复杂类型时。它让编译器根据初始化值推导变量类型,减少了冗余和错误。使用`auto`简化了迭代器声明和函数返回类型推导,但也带来挑战:类型推导可能不直观,未初始化的`auto`是错误的,且过度使用影响可读性。使用`auto&`和`auto*`明确引用和指针,`decltype`辅助复杂类型推导,保持适度使用以维持代码清晰。
308 1