C++的四个强制类型转换(未完成)

本文主要介绍了C++中的四种类型转换运算符。const_cast用于更改对象常量值;static_cast可进行明确定义的类型转换,能将左值显式转换为右值,也可向下转型;dynamic_cast借助RTTI实现基类与派生类指针或引用的安全转换;reinterpret_cast也有相关介绍。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

const_cast

说明

const_cast 是类型转换运算符之一。 它用于更改任何对象的常量值,或者我们可以说它用于删除任何对象的常量性质。
函数指针和成员函数指针不可用于const_cast[^1]

  1. 在任何程序中,const_cast 可用于将常量数据传递给另一个不接受常量数据的函数
#include <iostream>
using namespace std;
int change(int* p2) {
   return (*p2 * 10);
}
int main() {
   const int num = 100;
   const int *p = #
   int *p1 = const_cast <int *>(p);
   cout << change(p1);
   return 0;
}
// expre_const_cast_Operator.cpp
// compile with: /EHsc
#include <iostream>

using namespace std;
class CCTest {
public:
   void setNumber( int );
   void printNumber() const;
private:
   int number;
};

void CCTest::setNumber( int num ) { number = num; }

void CCTest::printNumber() const {
   cout << "\nBefore: " << number;
   const_cast< CCTest * >( this )->number--;
   cout << "\nAfter: " << number;
}

int main() {
   CCTest X;
   X.setNumber( 8 );
   X.printNumber();
}

测试代码

#include <iostream>
using namespace std;

struct type {
    int i;
    type() : i(3) {}
    void f(int v) const {
        // this->i = v;                 // 编译错误:this 是指向 const 的指针
        const_cast<type *>(this)->i = v;  // 只要该对象不是 const 就 OK
    }
};

const std::string &shortString(const std::string &s1, const std::string &s2) { return s1.size() < s2.size() ? s2 : s1; }
std::string &shortString(std::string &s1, std::string &s2) {
    auto &s3 = shortString(const_cast<const string &>(s1), const_cast<const string &>(s2));
    return const_cast<string &>(s3);
}

void ConstTest1() {
    const int a = 1;  ///>const int *
    int *p;
    p = const_cast<int *>(&a);  ///>只能强转为int*
    (*p)++;
    // 1.编译错误:invalid use of const_cast with type ‘int’, which is not a pointer, reference, nor a
    // pointer-to-data-member type
    //    int b = const_cast<int>(a);
    // 2. 编译错误: invalid const_cast from type ‘const int*’ to type ‘char*’
    //    char *c = const_cast<char *>(&a);
    // 3. 编译错误: invalid static_cast from type ‘const int*’ to type ‘char*’
    //    char *d = static_cast<char *>(&a);
    std::cout << a << std::endl;
    std::cout << *p << a << std::endl;
}
void ConstTest2() {
    int i = 3;
    const int a = i;  ///>const int *
    int &r = const_cast<int &>(a);
    int &dd = r;
    dd++;
    std::cout << a << i << std::endl;
}

void ConstTest3() {
    const char *pp;
    char *p = const_cast<char *>(pp);
    // 1. 编译错误: cannot convert ‘std::__cxx11::string {aka std::__cxx11::basic_string<char>}’ to ‘char*’ in
    // initialization
    //    char *p1 = static_cast<std::string>(pp);
    // 2. 编译错误: invalid conversion from ‘char’ to ‘char*’
    //    p = '1';
    // 3. 运行时崩溃
    //    *p = '1';///>crash
}
void ConstTest4() {
    const char pp = '2';  ///>const  char*
    // 1. 编译错误: invalid const_cast from type ‘const char*’ to type ‘int*
    //    char *p = const_cast<int *>(&pp);
    char *p = const_cast<char *>(&pp);
    *p += 1;
    std::cout << "p   " << p << std::endl;
    *p++;
    std::cout << "p   " << p << std::endl;
}

void ConstTest5() {
    //测试重载使用const_cast
    std::string a = "123123";
    std::string b = "123124141241";
    std::cout << shortString(a, b) << std::endl;
}

void ConstTest6() {
    int i = 3;  // 不声明 i 为 const
    const int &rci = i;
    const_cast<int &>(rci) = 4;  // OK:修改 i
    std::cout << "i = " << i << '\n';

    type t;  // 假如这是 const type t,则 t.f(4) 会是未定义行为
    t.f(4);
    std::cout << "type::i = " << t.i << '\n';

    const int j = 3;  // 声明 j 为 const
    int *pj = const_cast<int *>(&j);
    // *pj = 4;      // 未定义行为

    void (type::*pmf)(int) const = &type::f;  // 指向成员函数的指针
    // const_cast<void(type::*)(int)>(pmf);   // 编译错误:
}

int main() {
    // const_cast只改变常量的属性
    ConstTest1();
    ConstTest2();
    ConstTest3();
    ConstTest4();
    ConstTest5();
    ConstTest6();
    return -1;
}
1
21
43
p   3�i���
p   �i���
123124141241
i = 4
type::i = 4

static_cast

任何具有明确定义的类型转换,只要不包含底层const,都可以使用static_cast
注:顶层const是指指针本身是个常量(int i=1;int * const fck=&i;),底层const是指指针所指对象是个常量(const int i=1;const int *fck=&i;);

虽然我们不能隐式得将一个左值转换为右值,但是我们可以使用static_cast显示的将一个左值转换为右值。
static_cast 也能用来进行向下转型,它不会有运行时检查的开销,但只有在程序(通过某些其他逻辑)能够保证 表达式 所指向的对象肯定是 Derived 时才是安全的。

dynamic_cast

RTTI(运行时类别检查)的功能由dynamic_casttypeid两个运算符组成
dynamic_cast运算符主要用于将基类的指针或引用安全地转换成派生类的指针或引用(沿继承层次结构向上、向下和横向安全地转换指向类的指针和引用)。
dynamic_cast的使用形式如下:

//type必须是一个类 类型
dynamic_cast<type*>(e);///>e 必须是一个有效指针
dynamic_cast<type&>(e);///>e 必须是一个左值
dynamic_cast<type&&>(e);///>e 不能是左值
  • 转换成功的条件为:
  1. e的类型是目标类型type的公有派生类
  2. e的类型是目标类型type的公有基类
  3. e的类型是目标类型type的类型
  • 转换失败的代价:
  1. 若转换的目标type是指针类型,结果为0
  2. 若转换的目标type是引用类型,抛bad_cast异常(不存在所谓的空引用)。
  • 指针类型的转换
#include <iostream>
#include <memory>

using namespace std;

struct Base
{
    virtual ~Base() {}
};
 
struct Derived: Base
{
    virtual void name() {cout<<"Derived"<<endl;}
};
int main()
{
	//----------------------------------ok yo
	Base *p = new Derived();
	if(Derived*p1=dynamic_cast<Derived*>(p)){
      cout<<"ok yo"<<endl;
	}else{
      cout<<"no no no yo"<<endl;
	}

	//----------------------------------no no no yo
   Base *p1 = new Base();
	if(Derived*p2=dynamic_cast<Derived*>(p1)){
      p2->name();
      cout<<"ok yo"<<endl;
	}else{
      cout<<"no no no yo"<<endl;
	}
	
	//----------------------------------ok yo"
    Derived *p3 = new Derived();
	if(Base*p4=dynamic_cast<Derived*>(p3)){
      cout<<"ok yo"<<endl;
	}else{
      cout<<"no no no yo"<<endl;
	}
	return 0;
}

  • 引用类型转换
#include <iostream>
#include <memory>

using namespace std;

struct Base
{
    virtual ~Base() {}
};
 
struct Derived: Base
{
    virtual void name() {cout<<"Derived"<<endl;}
};
int main()
{
	Base b;
	Base &p1=b;
		//----------------------------------------ok
    try{
         Base & p2 = dynamic_cast< Base &>(p1);
         cout<<"OK "<<endl;
    }catch(bad_cast){
        cout<<"bad cast"<<endl;
    }
		//----------------------------------------bad cast
    try{
         Derived & p3 = dynamic_cast< Derived &>(p1);
         cout<<"OK "<<endl;
    }catch(bad_cast){
        cout<<"bad cast"<<endl;
    }

	return 0;
}
#include <iostream>
 
struct V
{
    virtual void f() {} // 必须为多态以使用运行时检查的 dynamic_cast
};
 
struct A : virtual V {};
 
struct B : virtual V
{
    B(V* v, A* a)
    {
        // 构造中转型(见后述 D 的构造函数中的调用)
        dynamic_cast<B*>(v); // 良好定义:v 有类型 V*,V 是 B 的基类,产生 B*
        dynamic_cast<B*>(a); // 未定义行为:a 有类型 A*,A 不是 B 的基类
    }
};
 
struct D : A, B
{
    D() : B(static_cast<A*>(this), this) {}
};
int main()
{
    D d; // 最终派生对象
    A& a = d; // 向上转型,可以用 dynamic_cast,但不是必须的

    D& new_d = dynamic_cast<D&>(a); // 向下转型
    B& new_b = dynamic_cast<B&>(a); // 侧向转型
}

reinterpret_cast

参考1
参考2

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

-西门吹雪

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值