AI智能
改变未来

一种 C++ 转换的非正式分类

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 转换

这种情况带有值类别转换,属于同对象转换。

// upcaststruct A{int x = 1;};struct B : A{};B b;static_cast<A&>(b).x = 2;std::cout << b.x << std::endl;// 输出:2
// downcaststruct 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
// sidecaststruct 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;}/* 输出:22*/

二、异对象转换

所有的非值类别转换都是异对象转换。

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() 1A::A(const A&) 12A::~A() 2A::~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*/
赞(0) 打赏
未经允许不得转载:爱站程序员基地 » 一种 C++ 转换的非正式分类