• c++隐式转换(implicit conversion)


    1.缘由

    最近在使用nlohmann的json,发现有些地方不是特别好用,所以就想自己修改一下(目的是为了增加类似jsoncpp中可以//增加注释的功能),在看源码的时候看到了一个迷惑的地方,就是解析json

    JSON_HEDLEY_WARN_UNUSED_RESULT
        static basic_json parse(detail::input_adapter&& i,
                                const parser_callback_t cb = nullptr,
                                const bool allow_exceptions = true)
        {
            basic_json result;
            parser(i, cb, allow_exceptions).parse(true, result);
            return result;
        }

    第一个参数我传入的是一个istream,但是这里接收的是一个类。

    调试的时候发现,先创建了一个input_adapater类

    class input_adapter
    {
      public:
        // native support
        JSON_HEDLEY_NON_NULL(2)
        input_adapter(std::FILE* file)
            : ia(std::make_shared<file_input_adapter>(file)) {}
        /// input adapter for input stream
        input_adapter(std::istream& i)
            : ia(std::make_shared<input_stream_adapter>(i)) {}
    
        /// input adapter for input stream
        input_adapter(std::istream&& i)
            : ia(std::make_shared<input_stream_adapter>(i)) {}
    
        input_adapter(const std::wstring& ws)
            : ia(std::make_shared<wide_string_input_adapter<std::wstring>>(ws)) {}
    
        input_adapter(const std::u16string& ws)
            : ia(std::make_shared<wide_string_input_adapter<std::u16string>>(ws)) {}
    
        input_adapter(const std::u32string& ws)
            : ia(std::make_shared<wide_string_input_adapter<std::u32string>>(ws)) {}
    
        /// input adapter for buffer
        template<typename CharT,
                 typename std::enable_if<
                     std::is_pointer<CharT>::value and
                     std::is_integral<typename std::remove_pointer<CharT>::type>::value and
                     sizeof(typename std::remove_pointer<CharT>::type) == 1,
                     int>::type = 0>
        input_adapter(CharT b, std::size_t l)
            : ia(std::make_shared<input_buffer_adapter>(reinterpret_cast<const char*>(b), l)) {}

    在这里找到了istream,一个构造函数。

    当时比较懵,还有这种使用方法?用c++这么久没有发现哪里有明确指出这种使用方法。潜意思中觉着可能是隐式转换。

    自己写了几个测试程序发现,确实是这样,类如果有一个对应类型的构造函数,是可以默认转换的。

    后来查资料,突然想起来,经常用的string不就是这样用吗?

    string str = "test";

    我们最常用的一种方法,这里就是调用了string里面const char*为参数的构造函数。可以调试查看xstring里面的这个函数

        basic_string(_In_z_ const _Elem * const _Ptr)
            : _Mybase()
            {    // construct from [_Ptr, <null>)
            _Tidy_init();
            assign(_Ptr);
            }

    2.c++类的类型转换(转换构造函数 Converting constructor)

    参考 https://en.cppreference.com/w/cpp/language/converting_constructor https://zh.cppreference.com/w/cpp/language/converting_constructor

    一个类的构造函数,如果没有声明explicit,并且传入的确定参数只有一个(这里的意思就是,不一定这个构造函数就一个参数,可以多个参数,但是其他参数都是有默认值的),那么这个就是转换构造函数。

    作用就是把一个类型隐式的转换成类。

    3.explicit

    参考 https://zh.cppreference.com/w/cpp/language/explicit

    与隐式转换对应出现的就是explicit关键字,既然提供了隐式转换,那么肯定也有禁止隐式转换的方法。explicit关键字就是声明在构造函数前,明确指定,不允许隐式转换构造,必须是明确的

    4.user-defined conversion

    参考 https://en.cppreference.com/w/cpp/language/cast_operator

    实际上上面的隐式转换属于这个范畴,就是用户自定义的转换。允许隐式和显式的转换类与一个其他类型。

    使用方法,就是operator加上要转换的类型,加上函数的括号,不能加参数,函数内部返回这个值。

    operator conversion-type-id
    operator 类型 ()
    {
        return 类型;
    }
    class C1
    {
    public:
        operator int()
        {
            return 1234;
        }  
    };
    
    int i1 = C1;

     mysql connector中的sqlstring

    class SQLString
    {
        std::string realStr;
    
        ~SQLString() {}
    
        SQLString() {}
    
        operator const std::string &() const
        {
            return realStr;
        }
    }
    SQLString a = "aaa";
    string b = a;

    就是在上面这种赋值的时候,会调用到这个函数,帮忙转换成另外一种类型,最好前后加const,防止改变内容

  • 相关阅读:
    Phantomjs 一些简单实用
    JAVA中关于数组的定义
    itextpdf JAVA 输出PDF文档
    MyBatis在insert插入操作时返回主键ID的配置
    卫士通加密机 控制台终端管理程序
    通过DOS、SHELL批处理命令加载Lib并编译和打包Java项目(或者运行项目)
    HTML单选按钮样式更换
    JAVA生成图片缩略图、JAVA截取图片局部内容
    JAVA笔记 之 Thread线程
    JAVA笔记 之 JDK新特性
  • 原文地址:https://www.cnblogs.com/studywithallofyou/p/11302767.html
Copyright © 2020-2023  润新知