【带头学C++】----- 九、类和对象 ---- 9.6 C++中的explicit关键字(c++11)

2023-12-14 04:47:25

目录

9.6 C++中的explicit关键字(c++11)

类型转换运算符可能产生意外结果


9.6 C++中的explicit关键字(c++11)

????????在C++中,explicit?是一个关键字,用于修饰单参数的构造函数,用来防止隐式类型转换的发生。是针对单参数的构造函数(或者除了第一个参数外其余参数都有默认值的多参构造)而言。

? ? ? ? 当一个构造函数被声明为?explicit?时,编译器将不会自动将该构造函数用于隐式类型转换。这意味着,在使用该构造函数创建对象时,必须显式地调用该构造函数。

class MyClass {
public:
    explicit MyClass(int x) {
        // 构造函数
    }
};

void foo(MyClass obj) {
    // 函数中使用 MyClass 对象
}

int main() {
    MyClass obj1(10);  // 正确,直接调用 explicit 构造函数
    //MyClass obj2 = 20;  // 错误,不能进行隐式类型转换
    MyClass obj3 = MyClass(20);  // 正确,显式调用 explicit 构造函数

    foo(obj1);  // 正确,传递 MyClass 对象作为参数
    //foo(30);  // 错误,不能进行隐式类型转换
    foo(MyClass(30));  // 正确,显式调用 explicit 构造函数创建 MyClass 对象

    return 0;
}

????????在上述示例中,MyClass?类有一个带有?int?类型参数的构造函数,并使用?explicit?关键字进行修饰。当声明对象时,如果使用该构造函数进行初始化,就必须显式地调用构造函数。在函数?foo?中,如果要传递?MyClass?对象作为参数,也必须显式地传递,否则会导致编译错误。?

????????实际上为了避免程序员在代码书写层面(就是你写代码自己看这个语句时候可能产生和你想的意思不一样的东西)的产生的歧义性,例如下面这个例子:

代码:

class MyString{
public:
    explicit MyString(int n){
        cout<<"MyString int n"<<endl;
    }
    MyString(const char* str){
        cout<<"MyString const char* str"<<endl;
    }
};
void test06(){
    //给字符串赋值?还是初始化
    //MyString str1 = 1; //直观的看上去,实际像是把1赋值给了str字符串一样(注意代码规范很重要)
    //有的人不在意代码的规范性,实际上给开发过程带来了很多浪费时间的去解读代码的时间
    //甚至有的人自己写的代码,过段时间再去看,就不知道写的是什么东西。
    //自己不写注释,自己都不注意这个东西,开发的东西只能是一堆s山。
    MyString str2(10);
    //寓意非常明确给字符串赋值
    MyString str3 = "abcd";
    MyString str4("abcd");
}
int main()
{
    test06();
    return 0;
}

类型转换运算符可能产生意外结果

? ? ? ? 在实践中,类很少提供类型转换运算符。在大多数情况下,如果类型转换自动发生,用户可能会感觉比较意外,而不是感觉受到了帮助。然而这条经验法则存在一种例外情况:582对于类来说,定义向 bool 的类型转换还是比较普遍的现象。

????????在 C++标准的早期版本中,如果类想定义一个向 bool 的类型转换,则它常常遇到一个问题:因为 bool 是一种算术类型,所以类类型的对象转换成 boo1 后就能被用在任何需要算术类型的上下文中。这样的类型转换可能引发意想不到的结果,特别是当istream含有向 bool的类型转换时,下面的代码仍将编译通过:

int i = 42;
cin << i; // 如果向bool 的类型转换不是显式的,则该代码在编译器看来将是合法的!

????????这段程序试图将输出运算符作用于输入流。因为 istream 本身并没有定义<<,所以本来代码应该产生错误。然而,该代码能使用 istream的bool类型转换运算符将 cin转换成bool,而这个bool值接着会被提升成int 并用作内置的左移运算符的左侧运算对象。这样一来,提升后的 bool值(1或0)最终会被左42个位置。这一结果显然与我们的预期不符。

以上是截取C++primer中对可能出现的隐式转换的语义的问题原因的解释,实际上编译器把这样的转换方式留给了程序员自己。

????????该规定存在一个例外,即如果表达式被用作条件,则编译器会将显式的类型转换自动应用于它。换句话说,当表达式出现在下列位置时,显式的类型转换将被隐式地执行:

  • if、while及do语句的条件部分
  • for语句头的条件表达式
  • 逻辑非运算符(!)逻辑或运算符 (II)逻辑与运算符 (&&)的运算对象.
  • 条件运算符(?:)的条件表达式。

通过使用?explicit?关键字,可以防止不必要的隐式类型转换,提高代码的可读性安全性

实际上,这个关键字进行简单了解一下就行了。初学者可以简单了解一下,不需要死记硬背,记住这个关键字是防止类进行隐式转换的就行。

文章来源:https://blog.csdn.net/Phofomy/article/details/134823500
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。