天天看點

【c++】explicit 隐式類類型轉換

上代碼

#include <iostream>
#include <sstream>
using namespace std;

class A 
{
    public:
        A(const string &book = "ab") : s(book)  {}
        int same_s(const A &a) const
        { return s == a.s; }
    private:
        string s;
};

int main(int argc ,char **argv)
{
    A c("aaa");
    string m = "aaa";
    cout << c.same_s(m) << endl;
}      

究其因

same_s應該接收一個類A的對象參數,但是這裡直接傳了一個字元串對象。過程這樣:編譯器接收一個string的對象,利用構造函數 A(const string &book = "ab") 生成臨時對象(隐性轉換),然後傳遞給same_s,臨時對象失效.

 注意: explicit 隻能用于類内部的構造函數的聲明上。

explicit和構造函數一起使用.

explicit constructor指明構造函數隻能顯式使用,目的是為了防止不必要的隐式轉化.

如何防止隐性轉換

構造函數加關鍵字explicit

#include <iostream>
#include <sstream>
using namespace std;

class A 
{
    public:
        explicit A(const string &book = "ab") : s(book)  {}
        int same_s(const A &a) const
        { return s == a.s; }
    private:
        string s;
};

int main(int argc ,char **argv)
{
    A c("aaa");
    string m = "aaa";
    cout << c.same_s(m) << endl;
}      

結果出錯

【c++】explicit 隐式類類型轉換

解決之道

字元串強制傳遞給構造函數

#include <iostream>
#include <sstream>
using namespace std;

class A 
{
    public:
        explicit A(const string &book = "ab") : s(book)  {}
        int same_s(const A &a) const
        { return s == a.s; }
    private:
        string s;
};

int main(int argc ,char **argv)
{
    A c("aaa");
    string m = "aaa";
    cout << c.same_s(A(m)) << endl;
}      

同理

對于 A a = string("hello")來說,如果參數為string的構造函數為explicit,則這樣初始化是錯誤的;如果不是explicit,則這樣初始化是正确的(先利用構造函數生成臨時對象,再把臨時對象通過指派操作符複制到新建立的對象上)。

對比實驗

對 

#include <iostream>
#include <sstream>
using namespace std;

class A 
{
  public:
    A(const string a) : s(a) {}
  private:
    string s;
};
int main(int argc ,char **argv)
{
  A a = string("hello");
}      
【c++】explicit 隐式類類型轉換

#include <iostream>
#include <sstream>
using namespace std;

class A 
{
  public:
    explicit A(const string a) : s(a) {}
  private:
    string s;
};
int main(int argc ,char **argv)
{
  A a = string("hello");
}