The formal classification method of C++ is directly classified by syntax, which is divided into: implicit conversion and explicit conversion. Implicit conversions are also known as standard conversions. Display conversion is further divided into: C-style conversion, function-style conversion, and C++-style conversion. C++ style conversion is static_cast
, dynamic_cast
, const_cast
and reinterpret_cast
these four kinds.
For a long time I have had this question: is the object before conversion and the object after conversion the same?
Now, I introduce an informal classification method, divided into: same-object transformation and different-object transformation. These two terms are made up by myself, just for the convenience of illustration.
- Same object conversion: The object after conversion is the same as the object before conversion, that is, a new object will not be constructed, and the original object will still be used.
- Different object conversion: The object after conversion and the object before conversion are not the same, that is, a new object will be constructed.
A typical case of these two conversions is described below.
First, the same object conversion
All value class transformations and their transformations are same-object transformations.
1. Value class conversion
The value class of C++ can static_cast
be , which belongs to the same object conversion. Note: Thestatic_cast<T&>()
semantics of and are not to convert an object to a reference, but to convert the object's value class so that it can be bound by the corresponding reference.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&&>(a);
b = 2;
std::cout << a << std::endl;
// 输出:2
2. OOP transformation with value class transformation
This case has a value class conversion, which is a same-object conversion.
// 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
3. Transform with Value Class const_cast
Transform
This case with value class conversion is also the same as object conversion. Note: By const_cast
modifying const
the original object is undefined behavior.
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
*/
Two, different object conversion
All non-value class conversions are out-of-object conversions.
1. Ordinary type conversion
// 标量类型
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. Pointer conversion
After conversion, the pointer itself is a different object, and the object pointed to by the pointer is the same object. This case also includes: OOP conversion with pointer, const_cast
conversion with pointer.
int* a = new int;
std::cout << a << std::endl;
int* && r = static_cast<int*>(a);
r = nullptr;
std::cout << a << std::endl;
/* 输出:
0x1ffdeb0 0x1ffdeb0
*/