C++学习总结(二十六)——RTTI类型检查,类指针类型转换

本文通过示例代码详细介绍了C++中的RTTI(运行时类型识别)机制及其应用,包括虚函数的作用、静态成员变量的覆盖以及dynamic_cast与static_cast在不同类型转换中的区别。

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

#include<iostream>
using namespace std;
//rtti实时类型检测
//成员变量的覆盖,静态变量也会覆盖。
//
class A
{
public:
	int num=0;
	static int data;
	virtual void run()//拥有虚函数,
	{
		cout << "Arun";
	}
};
int A::data = 0;
class B :public A
{
public:
	int num=0;
	static int data;
	void run()
	{
		cout << "Brun";
	}
	void test()
	{
		cout << "Btest";
	}
};
int B::data = 1;
void main1()
{
	B b1;
        b1.num = 10;
	b1.A::num = 20;
	cout << b1.num << ' ' << b1.A::num << endl;
	cout << b1.data << ' ' << b1.A::data<< endl;
	cin.get();
}
void main2()
{
	A *p1 = new A;
	A *p2 = new B;
	//不包含虚函数时,指针指向的对象都是A,包含虚函数时,指向B
	cout << typeid(*p1).name() << typeid(*p2).name() << endl;
	cout << typeid(p1).name() << typeid(p2).name() << endl;
	
	cin.get();
}
//dynamic进行数据类型转换
void main()
{
	A a1;
	B  b1;
	A *p1 = &a1;
	A *p2 = &b1;
	B *p3(nullptr);
	p3 = dynamic_cast<B*>(p2);
	 //dynamic类中必须包含虚函数,否则不能进行转换
	//根据虚函数表进行转换
	p3->test();
	cout << p3 << endl;
	p3 = dynamic_cast<B*>(p1);
	p3->test();
	cout << p3 << endl;

	std::cin.get();
}
//static进行数据类型转换
void main3()
{
	A a1;
	B  b1;
	A *p1 = &a1;
	A *p2 = &b1;
	B *p3(nullptr);
	p3 = static_cast<B*>(p2);//直接赋值地址,与有无虚函数无关
	p3->test();
	cout << p3 << endl;
	p3 = static_cast<B*>(p1);
	p3->test();
	cout << p3 << endl;

	std::cin.get();
}

### C++ 中的强制类型转换方法 在 C++ 编程语言中,强制类型转换是一种常见的需求。它允许程序员将一个数据类型的变量或表达式显式地转换为另一个数据类型C++ 提供了几种不同的类型转换机制来满足不同场景下的需求。 #### 静态转换 (`static_cast`) `static_cast` 是一种编译期执行的类型转换操作符,适用于非多态类型的转换。它可以安全地完成基本的数据类型之间的转换以及层次结构中的向上和向下转型(前提是这些关系是非多态的)。 例如,在数值类型之间进行转换时可以使用 `static_cast`: ```cpp double d = 3.14; int i = static_cast<int>(d); // 将 double 转换为 int ``` 此方法的优点在于其安全性较高,并且不会引入运行时开销[^3]。 #### 动态转换 (`dynamic_cast`) 与 `static_cast` 不同的是,`dynamic_cast` 主要用于处理涉及继承体系中的指针或多态对象间的类型转换。由于它是基于运行时类型信息 (RTTI, Run-Time Type Information),因此能够验证目标类型的合法性并返回相应的结果。如果尝试非法的操作,则会抛出异常或者返回空指针(针对指针的情况)。 下面是一个例子展示如何利用 `dynamic_cast` 进行基指向派生的安全下转: ```cpp class Base { virtual void f() {} }; class Derived : public Base {}; Base* basePtr = new Derived(); Derived* derivedPtr = dynamic_cast<Derived*>(basePtr); if(derivedPtr != nullptr){ std::cout << "成功转换!" << std::endl; } else { std::cout << "无法转换." << std::endl; } delete basePtr; ``` 需要注意的是,当涉及到复杂的继承链路时,`dynamic_cast` 的效率可能会受到影响,因为它需要查询 RTTI 数据库来进行判断[^2]。 #### 常量性修改 (`const_cast`) 尽管严格意义上不属于传统意义上的“强制类型转换”,但是为了完整性也在此提及一下。通过 `const_cast` 可以移除掉某个常量声明所附加上的不可变特性——即改变原先是只读的对象成为可写状态。然而这通常被认为是危险的做法,除非绝对必要才应考虑采用这种方式。 示例代码如下所示: ```cpp void func(const int *p) {} void test(){ const int a=0; int*b=const_cast<int*>(&a);//解除const限制 b[0]=5;//不推荐这样做,因为违反了原始定义意图 } ``` #### 解释性重铸 (`reinterpret_cast`) 最后介绍的一种形式叫做重新解释转换(`reinterpret_cast`) ,这是最底层也是风险最大的一转换手段之一 。 它直接作用于内存级别上对二进制位模式做简单的映射变换而没有任何语义层面的理解过程参与其中;换句话说就是把一块存储区域按照新的视角看待而已 —— 即使两者完全没有逻辑关联也没关系! 举个实际应用场合的例子来说吧 : 如果我们需要获取浮点数内部表示法的具体比特组成情况的话就可以借助这个工具实现目的啦~ ```cpp float fltValue = 123.45f; unsigned long ulIntRepresenation = reinterpret_cast<unsigned long&>(fltValue); std::cout << "Float value as integer bits:" << std::hex << ulIntRepresenation << "\n"; ``` 综上所述,每种类型转换都有各自适用范围及其局限所在,开发者应当依据具体业务需求选取恰当的方式加以运用从而达到最佳效果的同时兼顾程序健壮性和维护成本等问题考量因素进去综合评估决策才行哦~ ###
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值