選用刪除函式,而不是使用private未定義的函式
阿新 • • 發佈:2021-01-11
c++98中通常就函式定義為private,來表示這個函式不可用。比如常見的禁止複製建構函式或者複製拷貝函式。當然private也有些好的用法,比如單例中。
但是我們這裡討論的是刪除某個函式。
class NonCopyable { protected: NonCopyable() = default; ~NonCopyable() = default; private: NonCopyable(const NonCopyable& ) = delete; NonCopyable(NonCopyable&& ) = delete; NonCopyable& operator=(const NonCopyable& ) = delete; NonCopyable& operator=(NonCopyable&& ) = delete; };
用delete來表示刪除這個函式。
1. 為什麼要這麼做呢?
因為如果我們定義為private的時候,可能這個類的成員函式或者類的友元還是可以使用private定義的。
如果我們希望程式碼中不要每次都把相應複製建構函式或者複製拷貝函式都刪掉,可以繼承上述寫的類
class A : public NoCopyable {
// ....
};
當然還可以在NoCopyable中新增你想要刪除的函式。
當然上述程式碼中也存在一個問題,就是刪除函式最好是宣告為public
2. 為什麼刪除函式最好宣告為public?
因為當客戶端程式碼嘗試訪問一個宣告為private的刪除的函式時,編譯器會優先校驗可訪問性,然後判斷是否刪除。
所以會這時候可能得到錯誤的報錯資訊。
3. 任何函式都可已刪除
不僅時成員函式,還包括非成員函式和模板具現。
比如一個非成員函式
bool isLucky(int number); // 這裡我們接受一個int的,判斷他是否是幸運數字。
我們發現我們輸入int, float, double, bool都可以,因為這裡存在隱式轉換。
但是如果我們就想只接受一個int的呢,那麼我們就將不要的刪除就好了。
bool isLucky(bool) = delete;
bool isLucky(char) = delete;
bool isLucky(double) = delete;
注意刪除double,同時就刪除了float
因為當我們輸入一個float的變數時,將面臨一個隱式轉換。而轉換規則可以從float轉成int和double時,優先選用double.
而此時發現double的已經被刪除了,那麼編譯就會被阻止。
還有就是當這個時一個類內部的函式模板時,會遇到新的問題。
class Widget {
public:
tempalte <typename T>
void Process(T* ptr) {
}
private:
template<>
void Process(void*); // 編譯不通過,這裡我們想做一個讓傳入void*型別的引數的函式呼叫不能通過
};
因為 模板的特化必須在名字作用域而非類的作用域撰寫的。
所以我們改成這樣
class Widget {
public:
tempalte <typename T>
void Process(T* ptr) {
}
};
template<>
void Widget::Process<void>(void*) = delete;