一种 C++ 转换的非正式分类
2022-01-19 00:54
751 查看
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 */
相关文章推荐
- c++学习笔记——一种非法的类型转换
- C++类型向上转换的一种形式
- C++类型向上转换的一种形式
- C++的四种新式显示转换和一种旧式显示转换
- explicit:C++规定,当定义了只有一个参数的构造函数时,同时也定义了一种隐式的类型转换
- 从零开始学C++之继承(二):继承与构造函数、派生类到基类的转换
- 实战c++中的string系列--string到LPCWSTR的转换
- 浅谈C++中的构造函数分类及调用规则
- c++中double转换成string型(浮点数的格式化)
- C++的类型转换:static_cast、dynamic_cast、reinterpret_cast和const_cast
- 探究一种定长队列操作(C ,C++版本)
- C++的4种类型转换关键字及其特点
- C++在类之间调用static_cast转换时,需要复制构造函数
- 【C\C++】char[] 与 string 的转换
- 文本分类专题(ultimate 版)绝对是目前最全的C++版开源文本分类代码和最令人耳目一新的实验解释
- C++利用sstream进行数据类型转换
- C/C++中int/long/float/double数值类型与字符串互相转换[总结]
- C++各类型转换的总结
- C++特有类型转换整理
- c++显示类型转换