C++中不同類型默認(rèn)轉(zhuǎn)換的規(guī)則和機制詳解
不熟悉默認(rèn)類型轉(zhuǎn)換,真的很容易寫出bug?。。?/p>
在C++中,類型轉(zhuǎn)換是一個非常重要的概念。下面詳細(xì)講解C++中各種默認(rèn)類型轉(zhuǎn)換的規(guī)則和機制。
1. 算術(shù)類型轉(zhuǎn)換
整型提升 (Integral Promotion)
char c = 'A'; short s = 100; int i = c + s; // char和short都提升為int
算術(shù)轉(zhuǎn)換規(guī)則
// 轉(zhuǎn)換優(yōu)先級:long double > double > float > unsigned long long > long long > // unsigned long > long > unsigned int > int int i = 10; double d = 3.14; double result = i + d; // int轉(zhuǎn)換為double unsigned int u = 100; int j = -50; unsigned int result2 = u + j; // int轉(zhuǎn)換為unsigned int
2. 指針類型轉(zhuǎn)換
隱式指針轉(zhuǎn)換
// 派生類指針到基類指針
class Base {};
class Derived : public Base {};
Derived d;
Base* bp = &d; // 隱式向上轉(zhuǎn)換
// 數(shù)組到指針退化
int arr[5];
int* ptr = arr; // 數(shù)組退化為指針
// 0或nullptr到指針
int* p1 = 0;
int* p2 = nullptr;
// 任意指針到void*
int x = 10;
void* vp = &x;
3. 引用類型轉(zhuǎn)換
class Base {
public:
virtual void show() { cout << "Base" << endl; }
};
class Derived : public Base {
public:
void show() override { cout << "Derived" << endl; }
};
Derived d;
Base& br = d; // 派生類引用到基類引用
br.show(); // 輸出: Derived (多態(tài))
4. 限定符轉(zhuǎn)換 (Qualification Conversions)
const轉(zhuǎn)換
int x = 10; const int* cp = &x; // 非const到const // int* p = cp; // 錯誤: 不能去掉const限定 const int y = 20; // int* p2 = &y; // 錯誤: 不能去掉const限定 const int* cp2 = &y; // OK
volatile轉(zhuǎn)換
int normal = 10; volatile int vi = 20; volatile int* vp = &normal; // 非volatile到volatile // int* p = &vi; // 錯誤: 不能去掉volatile限定
5. 布爾轉(zhuǎn)換
// 以下情況會隱式轉(zhuǎn)換為bool
int* ptr = nullptr;
if (ptr) { // 指針到bool: nullptr→false, 其他→true
cout << "Pointer is valid" << endl;
}
int value = 10;
if (value) { // 算術(shù)類型到bool: 0→false, 非0→true
cout << "Value is non-zero" << endl;
}
6. 用戶定義類型轉(zhuǎn)換
轉(zhuǎn)換構(gòu)造函數(shù)
class MyString {
private:
char* str;
public:
// 轉(zhuǎn)換構(gòu)造函數(shù): const char* → MyString
MyString(const char* s) {
str = new char[strlen(s) + 1];
strcpy(str, s);
}
~MyString() { delete[] str; }
};
MyString s = "Hello"; // 隱式調(diào)用轉(zhuǎn)換構(gòu)造函數(shù)
類型轉(zhuǎn)換運算符
class SmartBool {
private:
bool value;
public:
SmartBool(bool b) : value(b) {}
// 類型轉(zhuǎn)換運算符: SmartBool → bool
operator bool() const {
return value;
}
};
SmartBool sb = true;
if (sb) { // 隱式調(diào)用operator bool()
cout << "SmartBool is true" << endl;
}
7. 標(biāo)準(zhǔn)轉(zhuǎn)換序列
C++編譯器會嘗試以下標(biāo)準(zhǔn)轉(zhuǎn)換序列:
class A {};
class B : public A {};
class C {};
void func(A a) {}
int main() {
B b;
func(b); // 標(biāo)準(zhǔn)轉(zhuǎn)換: B → A (派生類到基類)
// 可能的轉(zhuǎn)換序列:
// 1. 精確匹配
// 2. 提升轉(zhuǎn)換
// 3. 標(biāo)準(zhǔn)轉(zhuǎn)換
// 4. 用戶定義轉(zhuǎn)換
// 5. 省略號匹配
}
8. 顯式控制隱式轉(zhuǎn)換
explicit關(guān)鍵字
class ExplicitClass {
public:
explicit ExplicitClass(int x) {} // 禁止隱式轉(zhuǎn)換
};
void test(ExplicitClass ec) {}
int main() {
// ExplicitClass ec = 10; // 錯誤: 不能隱式轉(zhuǎn)換
ExplicitClass ec(10); // OK: 直接初始化
test(ExplicitClass(10)); // OK: 顯式轉(zhuǎn)換
}
刪除轉(zhuǎn)換函數(shù)
class NoConvert {
public:
NoConvert(int) {}
// 刪除不需要的轉(zhuǎn)換
NoConvert(double) = delete;
operator bool() = delete;
};
NoConvert nc(10); // OK
// NoConvert nc(3.14); // 錯誤: 使用已刪除的函數(shù)
// if (nc) {} // 錯誤: 使用已刪除的函數(shù)
9. 轉(zhuǎn)換的優(yōu)先級和歧義
class Ambiguous {
public:
Ambiguous(int x) {}
Ambiguous(double x) {}
};
void func(Ambiguous a) {}
int main() {
// func(10); // 歧義: int可以轉(zhuǎn)換為int或double
func(Ambiguous(10)); // 必須顯式指定
}
10. 最佳實踐和注意事項
避免意外的隱式轉(zhuǎn)換
// 使用explicit防止意外的構(gòu)造函數(shù)轉(zhuǎn)換 // 小心算術(shù)類型轉(zhuǎn)換的精度損失
注意符號性和大小
unsigned int u = 10;
int i = -5;
if (u > i) { // i轉(zhuǎn)換為unsigned int, 結(jié)果可能出乎意料
cout << "Unexpected result!" << endl;
}
使用static_cast進行顯式轉(zhuǎn)換
double d = 3.14; int i = static_cast<int>(d); // 明確的意圖
理解C++的類型轉(zhuǎn)換規(guī)則對于編寫安全、高效的代碼至關(guān)重要。在可能產(chǎn)生歧義或意外行為的地方,建議使用顯式轉(zhuǎn)換來明確意圖。
到此這篇關(guān)于C++中不同類型默認(rèn)轉(zhuǎn)換的規(guī)則和機制詳解的文章就介紹到這了,更多相關(guān)C++類型轉(zhuǎn)換內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
C++實現(xiàn)WebSocket服務(wù)器的案例分享
WebSocket是一種在單個TCP連接上進行全雙工通信的通信協(xié)議,與HTTP協(xié)議不同,它允許服務(wù)器主動向客戶端發(fā)送數(shù)據(jù),而不需要客戶端明確地請求,本文主要給大家介紹了C++實現(xiàn)WebSocket服務(wù)器的案例,需要的朋友可以參考下2024-05-05
詳解C語言中的ttyname()函數(shù)和isatty()函數(shù)的用法
這篇文章主要介紹了C語言中的ttyname()函數(shù)和isatty()函數(shù)的用法,是C語言入門學(xué)習(xí)中的基礎(chǔ)知識,需要的朋友可以參考下2015-09-09

