標籤:int str today pos 拷貝 ref c++ public blank
explicit建構函式
考慮一個類Date:
class Date{ int d,m,y; //...};void my_fact(Date d);void f(){ Date d{15}; //似乎合理:x變為{15,today.m,today.y} d = 15; //含混 my_fact(15); //含混 //...}
這最多是一段含混代碼,資料15和Date之間並沒有清晰的邏輯關聯。
但是,我們可以指明建構函式不能用作隱式類型轉換。如果建構函式的聲明帶有關鍵字explicit,它只能用於初始化和顯示類型轉換。例如:
class Date{ int d, m, y;public: explicit Date(int dd = 0,int mm=0,int yy = 0); //...};Date d1{15}; //OK:被看作顯式類型轉換Dated2 = Date{15}; //OK:顯式類型轉換Date d3 = {15}; //錯誤: = 方式的初始化不能進行隱式類型轉換Date d4 = 15; //錯誤: = 方式的初始化不能進行隱式類型轉換void f(){ my_fact(15); //錯誤:參數傳遞不能進行隱式類型轉換 my_fact({15}); //錯誤:參數傳遞不能進行隱式類型轉換 my_fact(Date{15}); //OK:顯式類型轉換}
用 = 進行初始化可以看做 拷貝初始化,一般而言,初始化器的副本會被方式待初始化的對象。但是,如果初始化器是一個右值,這種拷貝可能被最佳化掉(取消),而採用移動操作,省略 = 會將初始化變為顯式初始化。顯式初始化也稱為 直接初始化。
預設情況下,應該將單參數的建構函式生命為explicit。除非有更好的理由,否則應該按照這種預設的方式去做。如果定義隱士建構函式,最好寫下原因,否則代碼的維護者可能懷疑你疏忽了,或者不懂這一原則。
如果一個建構函式聲明為explicit且定義在類外,則在定義中不能重複explicit:
class Date{ int d,m,y;public: explicit Date(int dd);//....};Date::Date(int dd){/*...*/} //OKexplicit Date::Date(int dd){/*...*/} //錯誤
大多數explicit起重要作用的建構函式都接收單一參數。但是,explicit也可以用於五參或多個參數的建構函式。例如:
struct X{ explicit X(); explicit X(int, int);};X x1 = {}; //錯誤:隱式的X x2 = {1,2}; //錯誤:隱式的X x3{}; //OK:顯式的X x4{1,2}; //OK:顯式的int f(X);int i1 = f({}); //錯誤:隱式的int i2 = f({1,2}); //錯誤:隱式的int i3 = f(X{}); //OK:顯式的int i4 = f(X{1,2}); //OK:顯式的
More:參考連結
C++