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,防止改變內容

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM