zoukankan      html  css  js  c++  java
  • 语言基础(6):关键字explicit

    1、explicit含义

    C++中 explicit 被用来修饰只有一个参数的构造函数,作用是调用该构造函数必须是显示的(且要求只能放在函数声明处), 跟它相对应的单词是 implicit(隐含的、不言明的), 类构造函数默认情况下即声明为 implicit (因此C++没有此关键字)。

    如果不使用该关键字,调用只有一个参数的构造函数允许通过缺省的转换操作完成,过程可能通过如下两步执行(VS2017验证不是):

    • 将该构造函数参数对应数据类型的数据转换为该类对象;
    • 然后调用复制构造函数来实现构造对象;

    通过一个例子来说明 explicit 作用:

    class String{
          explicit String(int n);
          String(const char *p);
    };
    String s1 = 'a';       // 错误:不能做隐式char->String转换
    String s2(10);        // 可以:调用explicit String(int n);
    String s3 = String(10);   // 可以:调用explicit String(int n);再调用默认的复制构造函数
    String s4 = "Brian";       // 可以:隐式转换调用String(const char *p);再调用默认的复制构造函数
    String s5("Fawlty");       // 可以:正常调用String(const char *p);
    
    void f(String);
    
    String g()
    {
        f(10);         // 错误:不能做隐式int->String转换
        f("Arthur");   // 可以:隐式转换,等价于f(String("Arthur"));
        return 10;    // 错误:不能做隐式int->String转换
    }
    
    

    #2、例外的情况 前面说过,该参数只对有一个参数的构造函数有效,对于无参数和多个参数的构造函数,因为他们只能通过显示调用,所以使用 explicit 没有任何意义,但也存在例外情况,如下代码: ``` // Example.h #pragma once class CExample { public: CExample(void); public: ~CExample(void); public: int m_iFirst; int m_iSecond; public: CExample(int iFirst, int iSecond = 0); };

    // Example.cpp

    include "Example.h"

    CExample::CExample(void): m_iFirst(0) { }
    CExample::~CExample(void) { }
    CExample::CExample(int iFirst, int iSecond):m_iFirst(iFirst), m_iSecond(iSecond) { }

    //TestExplicitKey.cpp
    ...//其它头文件

    include "Example.h"

    int main()
    {
    CExample objOne; // 调用没有参数的构造函数
    CExample objTwo(12, 12); // 调用有两个参数的构造函数
    CExample objThree(12); // 同上,可以传一个参数是因为该构造函数的第二个参数有默认值
    /* 执行了隐式转换,等价于CExample temp(12);objFour(temp);注意这个地方调用了编译器为我们提供的默认复制构造函数 */
    CExample objFour = 12;
    return 0;
    }

    如果在构造函数声明中加入关键字explicit,如下:
    `explicit CExample(int iFirst, int iSecond = 0);`
    那么 CExample objFour = 12; 这条语句将不能通过编译。在vs下的编译错误提示如下:
    

    error C2440: 'initializing' : cannot convert from 'int' to 'CExample'
    Constructor for class 'CExample' is declared 'explicit'

    <br/>
    #3、何时不用explicit
    当我们需要隐式转换的时候,比如说String类的一个构造函数:
    `String(const char*);`
    定义成这样的好处,在需要隐式转化的时候编译器会自动地帮我们转换,标准库里面的String就是一个好的证明。具体来说:
    我们可以这样
    

    String str="helloworld"; // 直接调用构造函数

    String str="hello"+str+"world";
    // 调用重载的+操作符号,此过程相当于:
    String temp("hello"); // 调用构造函数
    String str=temp+str;
    String t("world"); // 调用构造函数
    String str=str+t;

    <br/>
    #总结
    <table><tr><td bgcolor = #233333><font color = #DDFFDD>
    1. explicit关键字只需用于类内的单参数构造函数前面,由于无参数的构造函数和多参数的构造函数总是显示调用,这种情况在构造函数前加explicit无意义;<br/>
    2. google的c++规范中提到explicit的优点是可以避免不合时宜的类型变换,缺点无。所以google约定所有单参数的构造函数都必须是显示的,只有极少数情况下拷贝构造函数可以不声明称explicit (例如作为其他类的透明包装器的类或者需要隐式转换的情况);<br/>
    3. effective c++中说:被声明为explicit的构造函数通常比其non-explicit兄弟更受欢迎。因为它们禁止编译器执行非预期(往往也不被期望)的类型转换。除非我有一个好理由允许构造函数被用于隐式类型转换,否则我会把它声明为explicit,鼓励大家遵循相同的政策;<br/>
    </font></td></tr></table>
  • 相关阅读:
    Machine Learning、Date Mining、IR&NLP 会议期刊论文推荐
    Natural Language Processing, 2017, Mar.29, Weekly Report
    【Turing Award】Robin Milner And Butler W. Lampson
    【word2vec】Distributed Representation——词向量
    【Java】HashTable和HashMap区别
    String, StringBuffer,StringBuilder的区别
    【Java】自动类型转换规则
    【Miktex】使用教程以及数学符号整理总结
    【JDK】各个版本垃圾收集器
    【Java】异常类处理层次
  • 原文地址:https://www.cnblogs.com/wnwin/p/10697405.html
Copyright © 2011-2022 走看看