当前位置: 代码网 > it编程>编程语言>C/C++ > C++强制类型转化、const的全解析

C++强制类型转化、const的全解析

2026年02月12日 C/C++ 我要评论
1.c方式强制类型((type)(a))转换存在的问题(1)任意类型之间都可以进行转换,编译器很难判断其正确性(2)在源码中无法快速定位所有使用强制类型转换的语句c++中的强制类型转换,语法:xxx_

1.c方式强制类型((type)

(a))转换存在的问题

(1)任意类型之间都可以进行转换,编译器很难判断其正确性

(2)在源码中无法快速定位所有使用强制类型转换的语句

c++中的强制类型转换,语法:xxx_cast<type>(a)

(1)static_cast

用于基本类型间的转换,不能用于基本类型指针间的转换,用于有继承关系类对象之间的转换和类指针之间的转换

(2)const_cast

用于去除变量的只读属性,强制转换的目标类型必须是指针或引用

(3)dynamic_cast

用于有继承关系的类指针间的转换,用于有交叉关系的类指针间的转换,具有类型检查的功能,需要虚函数的支持

通过子类指针去指向父类指针

#include <iostream>
using namespace std;
class base
{
public:
    base()
    {
        cout << "base::base()" << endl;
    }
    virtual void func()
    {
        cout << "base::func()" << endl;
    }
    virtual ~base()
    {
        cout << "base::~base()" << endl;
    }
};
class derived : public base
{
public:
    virtual void func()
    {
        cout << "derived::func()" << endl;
    }
};
int main()
{
    base* p = new base;                            //初始化父类指针
    derived* pd = dynamic_cast<derived*>(p);    //由于父类指针指向的是父类,只有父类虚函数表,没有子类的虚函数表,所以转换失败
                              //如果使用static_cast或者reinterpret_cast,则能成功,调用pd->func则打印base::func()    
    //pd->func();                               //由于pd=0,所以这里会程序崩溃
    cout << "pd = " << pd << endl;              //转换失败,打印 0
    delete p;
    p = reinterpret_cast<base*>(new derived);      //等价于p =  (base*)new derived; 或者 p =  reinterpret_cast<base*>(new derived)
                              //或者static_cast
    pd = dynamic_cast<derived*>(p);              //由于父类指针指向的是子类,所以有子类虚函数表
    pd->func();                                  //打印"derived::func()"
    cout <<"pd = " << pd <<endl;                //转换成功,打印地址值
    delete p;
    return 0;
}
  • 父类(无虚函数)强制转为子类时,可以用static_cast或者reinterpret_cast进行强转

(4)reinterpret_cast

用于指针类型间的转换,用于整数与指针类型间的强转

#include <stdio.h>
void staic_cast_demo() {
	int i = 0x12345;
	char c = 'c';
	int* pi = &i;
	char* pc = &c;
	c = static_cast<char>(i);
	// pc = static_cast<char*>(pi); //error,不能用于基本类型指针间的转换
}
void const_cast_demo() {
	const int& j = 1; //只读变量
	int& k = const_cast<int&>(j); //去除只读变量,可以通过k修改变量的值
	const int x = 2; //常量,存在符号表里
	int& y = const_cast<int&>(x); //内存会给这个常量分配一个临时的空间,并且y指向这块空间
	// int z = const_cast<int>(x); //error,目标类型必须是指针或引用
	k = 5;
	printf("k=%d\n", k); //5
	printf("j=%d\n", j); //5
	y = 8;
	printf("x=%d\n", x); //2
	printf("y=%d\n", y); //8
	printf("&x=%p\n", &x); //&x=0000006db754f964
	printf("&y=%p\n", &y); //&y=0000006db754f964
}
void reinterpret_cast_demo() {
	int i = 0;
	char c = 'c';
	int* pi = &i;
	char* pc = &c;
	pc = reinterpret_cast<char*>(pi);
	pi = reinterpret_cast<int*>(pc);
	pi = reinterpret_cast<int*>(i);
	// c = reinterpret_cast<char>(i); //error,不能用于基本类型间的转换
}
void dynamic_cast_demo() {
	int i = 0;
	int* pi = &i;
	// char* pc = dynamic_cast<char*>(pi); error,只能用于有继承关系的类指针间的转换
}
int main() {
	staic_cast_demo();
	const_cast_demo();
}

2.const什么是只读变量,什么是常量?

(1)只有用字面量初始化的const常量才会进入符号表

const int x=1;

(2)使用其他变量初始化的const常量仍然是只读变量

const int& rx=x;

(3)被volatile修饰的const常量是易变的,因此不会进入符号表

即在编译期间不能直接确定初始值的const标识符,都被作为只读变量处理,只读变量仅仅意味着被const修饰的变量不能出现在赋值符号左边

#include <stdio.h>
int main() {
	const int x = 1;
	const int& rx = x;
	int& nrx = const_cast<int&>(rx);
	nrx = 5;
	printf("x=%d\n", x);
	printf("rx=%d\n", rx);
	printf("nrx=%d\n", nrx);
	printf("&x=%d\n", &x);
	printf("&rx=%d\n", &rx);
	printf("&nrx=%d\n", &nrx);
	volatile const int y = 2; //加了volatile就是只读变量
	int* p = const_cast<int*>(&y);
	*p = 6;
	printf("y=%d\n", y); //6
	printf("p=%p\n", p); //p=000000d6682ff8d4
	const int z = y;
	p = const_cast<int*>(&z);
	*p = 7;
	printf("z=%d\n", z);
	printf("p=%p\n", p);
	char c = 'c';
	char& rc = c;
	const int& trc = c; //引用的类型不同,则会生成一个新的只读变量,即trc是只读变量
	rc = 'a';
	printf("c=%c\n", c);
	printf("rc=%c\n", rc);
	printf("trc=%c\n", trc);
}

运行结果:

3.引用与指针的关系

指针:

(1)指针是一个变量,值为一个内存地址,不需要初始化,可以保存不同的地址

(2)通过指针可以访问对应内存地址中的值

(3)指针可以被const修饰为常量或只读变量

引用:

(1)引用只是变量的一个新名字,对引用的操作都会传递到代表的变量

(2)const引用使其代表的变量具有只读属性

(3)引用必须在定义时初始化,之后无法代表其他变量

#include <stdio.h>
int main() {
    // const 常量
    const int c = 0;    //const局部变量
    int* p = (int*)&c; //使用&操作符,会分配空间      int* p = (int*)&c  -> const int& p = c;
    *p = 5;
    printf("c = %d,*p=%d\n", c, *p);  // c = 0,*p=5 实际没有改变c自身的值。
    // const 只读变量 (一般用在引用或者指针上)
    int d = 1;          // 临时变量,自身可读写
    const int& p2 = d;   // 其实这个p2 是个只读变量(可以通过const_cast去更改)
    int& p3 = const_cast<int&>(p2);
    p3 = 100;
    printf("d = %d  p2 = %d\n", d, p2);  //d = 100  p2 = 100  实际目标d被改变了,因为d是个可读写的变量。
                                         //所以引用修饰的const只是个标志,到底能不能更改目标,需要引用的目标类型是否是const
    const int d2 = 1;          // 引用的目标类型是const
    const int& p4 = d2;   // 其实这个p4 是个只读变量(可以通过const_cast去更改)
    int& p5 = const_cast<int&>(p4);
    p5 = 100;
    printf("d2 = %d  p4 = %d\n", d2, p4);  //d = 100  p2 = 100  实际目标d2没有改变,因为d2是个常量。 
    return 0;
}

到此这篇关于c++强制类型转化、const的理解的文章就介绍到这了,更多相关c++强制类型转化内容请搜索代码网以前的文章或继续浏览下面的相关文章希望大家以后多多支持代码网!

(0)

相关文章:

  • C++的虚继承实现示例

    C++的虚继承实现示例

    一、虚继承的核心定位:解决菱形继承的痛点在讲解虚继承前,先明确其诞生的背景——菱形继承(钻石继承) 是多重继承的典型问题,而虚继承是c+... [阅读全文]
  • C++线程锁的使用

    C++线程锁的使用

    一、基础概念:锁的核心分类在讲解具体工具前,先明确c++锁的两个核心维度:基础锁类型(提供原始的加锁/解锁能力):std::mutex、std::recursi... [阅读全文]
  • C++类成员指针的实现示例

    C++类成员指针的实现示例

    一、类成员指针的核心定位类成员指针是c++中专门指向“类的成员”(而非具体对象的成员)的特殊指针,和普通指针的核心区别:普通指针:直接指... [阅读全文]
  • C++ CPU的局部性原理两种类型解析

    C++ CPU的局部性原理两种类型解析

    cpu的局部性原理github地址有梦想的电信狗前言在实际编程中,我们常会发现:逻辑相同的代码,仅仅改变数据访问顺序,性能却可能相差数倍。造成这种差异的根本原因... [阅读全文]
  • 深入理解 Qt 中的事件循环

    深入理解 Qt 中的事件循环

    在 qt 框架中,事件循环(event loop)是支撑图形界面(gui)响应性、异步操作处理的核心机制。无论是按钮点击、窗口拖动,还是网络请求、定时器触发,最... [阅读全文]
  • C++ explicit显式关键字的实现

    C++ explicit显式关键字的实现

    一、explicit 关键字的核心定义explicit 是c++中的修饰符关键字,唯一的作用场景是修饰类的构造函数,它的核心功能是:禁止编译器对被修饰的构造函数... [阅读全文]

版权声明:本文内容由互联网用户贡献,该文观点仅代表作者本人。本站仅提供信息存储服务,不拥有所有权,不承担相关法律责任。 如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 2386932994@qq.com 举报,一经查实将立刻删除。

发表评论

验证码:
Copyright © 2017-2026  代码网 保留所有权利. 粤ICP备2024248653号
站长QQ:2386932994 | 联系邮箱:2386932994@qq.com