文章目錄
- 1. **防止隱式類型轉換**
- 示例1:沒有使用`explicit`
- 示例2:使用`explicit`
- 2. **防止拷貝初始化**
- 示例1:沒有使用`explicit`
- 示例2:使用`explicit`
- 3. **防止隱式類型轉換的鏈式調用**
- 示例1:沒有使用`explicit`
- 示例2:使用`explicit`
- 4. **防止隱式類型轉換的歧義**
- 示例1:沒有使用`explicit`
- 示例2:使用`explicit`
- 總結
在C++中,
explicit
關鍵字用于修飾構造函數和轉換運算符,其主要目的是防止隱式類型轉換和拷貝初始化,從而提高代碼的可讀性和安全性。以下是
explicit
的詳細作用和使用場景:
1. 防止隱式類型轉換
當構造函數被聲明為explicit
時,它不能用于隱式類型轉換。這意味著不能通過單個參數的構造函數隱式地將一個類型轉換為另一個類型。
示例1:沒有使用explicit
class MyClass {
public:MyClass(int x) : value(x) {} // 非explicit構造函數int value;
};void printMyClass(MyClass obj) {std::cout << obj.value << std::endl;
}int main() {printMyClass(10); // 隱式調用 MyClass(int) 構造函數return 0;
}
在這個例子中,MyClass(int)
構造函數是非explicit
的,因此可以隱式地將int
類型轉換為MyClass
類型。調用printMyClass(10)
時,會隱式地調用MyClass(10)
構造函數。
示例2:使用explicit
class MyClass {
public:explicit MyClass(int x) : value(x) {} // explicit構造函數int value;
};void printMyClass(MyClass obj) {std::cout << obj.value << std::endl;
}int main() {// printMyClass(10); // 錯誤:無法隱式調用 MyClass(int) 構造函數printMyClass(MyClass(10)); // 顯式調用 MyClass(10) 構造函數return 0;
}
在這個例子中,MyClass(int)
構造函數被聲明為explicit
,因此不能隱式地將int
類型轉換為MyClass
類型。調用printMyClass(10)
時,會報錯,必須顯式地調用MyClass(10)
構造函數。
2. 防止拷貝初始化
explicit
構造函數不能用于拷貝初始化,但可以用于直接初始化。
示例1:沒有使用explicit
class MyClass {
public:MyClass(int x) : value(x) {} // 非explicit構造函數int value;
};int main() {MyClass obj = 10; // 拷貝初始化,隱式調用 MyClass(int) 構造函數return 0;
}
在這個例子中,MyClass(int)
構造函數是非explicit
的,因此可以用于拷貝初始化。
示例2:使用explicit
class MyClass {
public:explicit MyClass(int x) : value(x) {} // explicit構造函數int value;
};int main() {// MyClass obj = 10; // 錯誤:無法隱式調用 MyClass(int) 構造函數MyClass obj(10); // 直接初始化,顯式調用 MyClass(int) 構造函數return 0;
}
在這個例子中,MyClass(int)
構造函數被聲明為explicit
,因此不能用于拷貝初始化。必須使用直接初始化的方式顯式調用構造函數。
3. 防止隱式類型轉換的鏈式調用
explicit
可以防止多個隱式類型轉換的鏈式調用,從而避免潛在的錯誤。
示例1:沒有使用explicit
class MyClass {
public:MyClass(int x) : value(x) {} // 非explicit構造函數int value;
};class YourClass {
public:YourClass(MyClass obj) : myObj(obj) {} // 非explicit構造函數MyClass myObj;
};int main() {YourClass obj = 10; // 隱式調用 MyClass(int) 和 YourClass(MyClass)return 0;
}
在這個例子中,MyClass(int)
和YourClass(MyClass)
構造函數都是非explicit
的,因此可以隱式地將int
類型轉換為MyClass
類型,再將MyClass
類型轉換為YourClass
類型。
示例2:使用explicit
class MyClass {
public:explicit MyClass(int x) : value(x) {} // explicit構造函數int value;
};class YourClass {
public:explicit YourClass(MyClass obj) : myObj(obj) {} // explicit構造函數MyClass myObj;
};int main() {// YourClass obj = 10; // 錯誤:無法隱式調用 MyClass(int) 和 YourClass(MyClass)YourClass obj(MyClass(10)); // 顯式調用 MyClass(10) 和 YourClass(MyClass)return 0;
}
在這個例子中,MyClass(int)
和YourClass(MyClass)
構造函數都被聲明為explicit
,因此不能隱式地進行類型轉換。必須顯式地調用構造函數。
4. 防止隱式類型轉換的歧義
在某些情況下,多個構造函數可能導致隱式類型轉換的歧義。使用explicit
可以避免這種歧義。
示例1:沒有使用explicit
class MyClass {
public:MyClass(int x) : value(x) {} // 非explicit構造函數MyClass(double x) : value(static_cast<int>(x)) {} // 非explicit構造函數int value;
};void printMyClass(MyClass obj) {std::cout << obj.value << std::endl;
}int main() {printMyClass(10); // 隱式調用 MyClass(int) 構造函數printMyClass(10.5); // 隱式調用 MyClass(double) 構造函數return 0;
}
在這個例子中,MyClass(int)
和MyClass(double)
構造函數都是非explicit
的,因此可以隱式地將int
和double
類型轉換為MyClass
類型。
示例2:使用explicit
class MyClass {
public:explicit MyClass(int x) : value(x) {} // explicit構造函數explicit MyClass(double x) : value(static_cast<int>(x)) {} // explicit構造函數int value;
};void printMyClass(MyClass obj) {std::cout << obj.value << std::endl;
}int main() {// printMyClass(10); // 錯誤:無法隱式調用 MyClass(int) 構造函數// printMyClass(10.5); // 錯誤:無法隱式調用 MyClass(double) 構造函數printMyClass(MyClass(10)); // 顯式調用 MyClass(int) 構造函數printMyClass(MyClass(10.5)); // 顯式調用 MyClass(double) 構造函數return 0;
}
在這個例子中,MyClass(int)
和MyClass(double)
構造函數都被聲明為explicit
,因此不能隱式地進行類型轉換。必須顯式地調用構造函數,避免了潛在的歧義。
總結
explicit
關鍵字的主要作用是防止隱式類型轉換和拷貝初始化,從而提高代碼的可讀性和安全性。在設計類時,如果某個構造函數或轉換運算符不應該被隱式調用,應該使用explicit
關鍵字進行修飾。