拨开荷叶行,寻梦已然成。仙女莲花里,翩翩白鹭情。
IMG-LOGO
主页 文章列表 一种 C++ 转换的非正式分类

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

白鹭 - 2022-02-11 2083 0 0

C++ 正式分类方法是直接按语法分类,分为:隐式转换和显示转换,隐式转换又称为标准转换,显示转换又分为:C 风格转换、函式风格转换、C++ 风格转换,C++风格转换就是 static_castdynamic_castconst_castreinterpret_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

标签:

0 评论

发表评论

您的电子邮件地址不会被公开。 必填的字段已做标记 *