C++ 正式分類方法是直接按語法分類,分為:隱式轉換和顯示轉換,隱式轉換又稱為標準轉換,顯示轉換又分為:C 風格轉換、函式風格轉換、C++ 風格轉換,C++風格轉換就是 static_cast、dynamic_cast、const_cast 和 reinterpret_cast 這 4 種,
有很長一段時間我都有這樣的疑問:轉換前的物件和轉換后的物件是不是同一個?
現在,我引入一種非正式分類方法,分為:同物件轉換和異物件轉換,這兩個術語是我自己編的,只是為了方便說明問題,
- 同物件轉換:轉換后的物件和轉換前的物件是同一個,也就是不會構造一個新的物件,還是使用原來的物件,
- 異物件轉換:轉換后的物件和轉換前的物件不是同一個,也就是會構造一個新的的物件,
下面分別說明這兩種轉換的典型情況,
一、同物件轉換
所有的值類別轉換及其變形都是同物件轉換,
1. 值類別轉換
C++ 的值類別可以使用 static_cast 進行轉換,屬于同物件轉換,注意:static_cast<T&>() 和 static_cast<T&&>() 的語意不是將一個物件轉換為一個參考,而是轉換物件的值類別,使其能被對應的參考系結,
// 左值轉換為左值
int a = 1;
static_cast<int&>(a) = 2;
std::cout << a << std::endl;
// 輸出:2
// 左值轉換為右值
int a = 1;
int&& b = static_cast<int&&>(a);
b = 2;
std::cout << a << std::endl;
// 輸出:2
// 右值轉換為右值,轉換前物件為非字面量
int a = 1;
int&& b = static_cast<int&&>(static_cast<int&&>(a));
b = 2;
std::cout << a << std::endl;
// 輸出:2
2. 借助值類別轉換進行 OOP 轉換
這種情況帶有值類別轉換,屬于同物件轉換,
// upcast
struct A
{
int x = 1;
};
struct B : A
{
};
B b;
static_cast<A&>(b).x = 2;
std::cout << b.x << std::endl;
// 輸出:2
// downcast
struct A
{
int x = 1;
};
struct B : A
{
};
B b;
static_cast<B&>(static_cast<A&>(b)).x = 2;
std::cout << b.x << std::endl;
// 輸出:2
// sidecast
struct A1
{
virtual void f1() {}
int x = 1;
};
struct A2
{
virtual void f2() {}
int y = 1;
};
struct B : A1, A2
{
};
B b;
dynamic_cast<A2&>(static_cast<A1&>(b)).y = 2;
std::cout << b.y << std::endl;
// 輸出:2
2. 借助值類別轉換進行 const_cast 轉換
這種情況帶有值類別轉換,也是同物件轉換,注意:通過 const_cast 修改原本為 const 的物件是未定義行為,
struct A
{
int x = 1;
};
{
int a;
const_cast<int&>(const_cast<const int&>(a)) = 2;
std::cout << a << std::endl;
}
{
A a;
const_cast<A&>(const_cast<const A&>(a)).x = 2;
std::cout << a.x << std::endl;
}
/* 輸出:
2
2
*/
二、異物件轉換
所有的非值類別轉換都是異物件轉換,
1. 普通的型別轉換
// 標量型別
int a = 1;
int&& b = static_cast<int>(a);
b = 2;
std::cout << a << std::endl;
// 輸出:1
// 型別別
struct A
{
A() {
std::cout << "A::A() " << x << std::endl;
}
A(const A&) {
std::cout << "A::A(const A&) " << x << std::endl;
}
~A() {
std::cout << "A::~A() " << x << std::endl;
}
int x = 1;
};
A a;
A&& b = static_cast<A>(a);
b.x = 2;
std::cout << b.x << std::endl;
/* 輸出:
A::A() 1
A::A(const A&) 1
2
A::~A() 2
A::~A() 1
*/
2. 指標轉換
轉換之后,指標本身是異物件,指標所指的物件是同物件,這種情況也包含:借助指標進行 OOP 轉換,借助指標進行 const_cast 轉換,
int* a = new int;
std::cout << a << std::endl;
int* && r = static_cast<int*>(a);
r = nullptr;
std::cout << a << std::endl;
/* 輸出:
0x1ffdeb0 0x1ffdeb0
*/
本文來自博客園,作者:mkckr0,轉載請注明原文鏈接:https://www.cnblogs.com/mkckr0/p/15820624.html
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/415243.html
標籤:其他
