Una taxonomía informal de las transformaciones de C++

El método de clasificación formal de C++ se clasifica directamente por sintaxis, que se divide en: conversión implícita y conversión explícita. Las conversiones implícitas también se conocen como conversiones estándar. La conversión de visualización se divide a su vez en: conversión de estilo C, conversión de estilo de función y conversión de estilo C++. La conversión de estilo C++ es static_cast, dynamic_casty estosconst_cast cuatro tipos.reinterpret_cast

Durante mucho tiempo he tenido esta pregunta: ¿el objeto antes de la conversión y el objeto después de la conversión son iguales?

Ahora, presento un método de clasificación informal, dividido en: transformación del mismo objeto y transformación de objetos diferentes. Estos dos términos están compuestos por mí mismo, solo por conveniencia de ilustración.

  • Conversión del mismo objeto: el objeto después de la conversión es el mismo que el objeto antes de la conversión, es decir, no se construirá un nuevo objeto y se seguirá utilizando el objeto original.
  • Conversión de objeto diferente: el objeto después de la conversión y el objeto antes de la conversión no son lo mismo, es decir, se construirá un nuevo objeto.

A continuación se describe un caso típico de estas dos conversiones.

Primero, la misma conversión de objetos.

Todas las transformaciones de clase de valor y sus transformaciones son transformaciones del mismo objeto.

1. Conversión de clase de valor

La clase de valor de C++ se static_castpuede , que pertenece a la misma conversión de objetos. Nota: Lastatic_cast<T&>() semántica de y no es convertir un objeto en una referencia, sino convertir la clase de valor del objeto para que pueda vincularse a la referencia correspondiente.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. Transformación OOP con transformación de clase de valor

Este caso tiene una conversión de clase de valor, que es una conversión del mismo objeto.

// 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. Transformar con transformación de clase de  const_cast valor

Este caso con la conversión de clases de valor también es el mismo que la conversión de objetos. Nota: Al  const_cast modificar  const el objeto original no se define el comportamiento.

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
*/

Dos, conversión de objetos diferentes

Todas las conversiones de clase sin valor son conversiones fuera de objeto.

1. Conversión de tipo ordinario

// 标量类型
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. Conversión de puntero

Después de la conversión, el puntero en sí es un objeto diferente y el objeto al que apunta el puntero es el mismo objeto. Este caso también incluye: conversión OOP con puntero,  const_cast conversión con puntero.

int* a = new int;
std::cout << a << std::endl;
int* && r = static_cast<int*>(a);
r = nullptr;
std::cout << a << std::endl;
/* 输出:
0x1ffdeb0 0x1ffdeb0
*/

Supongo que te gusta

Origin blog.csdn.net/weixin_55305220/article/details/123578743
Recomendado
Clasificación