剑指offer【1】——C++类型转换关键字浅析,空类型sizeof

1、C++有哪四个类型转换的关键字?各有什么特点?分别在什么场景下使用?

**c语言的强制类型转换:**可以对基本数据类型进行类型转换,窄数据类型向宽数据类型转换是安全的,宽数据类型向窄数据类型转换是不安全的,可能损失精度。格式是如下:

TYPE1 a=(TYPE2) b;

**static_cast:**除了可以实现C语言强制数据类型转换相同的基本数据类型的转换外,还可以实现对象类型的转换,其中转换的两个类型必须是继承关系,上行转换(子类向基类转化)是安全的,下行转换时不安全的。static_cast不能修改原变量的const,volatile属性。格式如下:

 TYPE1 a=static_cast<TYPE2>(b);

**const_cast:**用于修改变量的const和volatile属性,常量指针被转化成非常量的指针,并且仍然指向原来的对象;常量引用被转换成非常量的引用,并且仍然指向原来的对象;const_cast一般用于修改底指针,如const char *p形式。格式如下:

const TYPE b;
TYPE *a=const_cast<TYPE*>(&b);
TYPE &c=const_cast<TYPE&>(b);//如果是类类型,对a和c的改变就是对b的改变,如果是基本数据
                             //类型,对a和c的改变不影响b的值(亲测是这样)。


//一个实例:
#include <iostream>
class A{
public:
	A(int t) :i(t){};
	int i;
};

int main(){
	const A a(10);
	A *b = const_cast<A*>(&a);
	A &c = const_cast<A&>(a);
	//a.a = 100;   //不能进行修改,因为A是const
	std::cout << a.i << std::endl;
	b->i = 11;   //同时也改变了a的成员
	std::cout << a.i <<"    "<<b->i<< std::endl;
	c.i = 12;
	std::cout << a.i <<"    "<<c.i<< std::endl;
}
//输出为:
//10
//11    11
//12    12

**dynamic_cast:**在子类和父类之间转换,可以在继承关系、兄弟关系或对象与void*之间进行转换,上行转换(子类向基类转化)是安全的,这个与static_cast一样,下行转换static_cast是不安全的,但是dynamic_cast实在运行时进行动态转换,同时会进行安全检查,下行转换将返回一个空指针。dynamic_cast还支持交叉转换,即在兄弟类型间进行转换,转换个结果为空指针。值得注意的是,dynamic_cast转换的父类必须含有虚函数,因为运行时类型检查需要运行时类型信息,而这个信息存储在类的虚函数表中。格式如下:

//上下行转换
classB
{
public:
int m_iNum;
virtual void foo();
};
 
classD:public B
{
public:
char* m_szName[100];
};
 
void func(B* pb,D* ptr)
{
//上行转换是安全的
D* pd1=static_cast<D*>(pb);
D* pd2=dynamic_cast<D*>(pb);
//下行转换static_cast是不安全的,dynamic_cast是相对安全的
B* ptr1=static_cast<B*>(ptr);   //不安全
B* ptr2=dynamic_cast<B*>(ptr);   //null pointer

}


//交叉转换
classA
{
public:
intm_iNum;
virtual void f(){}
};
class B:public A
{
};
class D:public A
{
};
void foo()
{
B*pb=newB;
pb->m_iNum=100;
//D*pd1=static_cast<D*>(pb);//compile error
D*pd2=dynamic_cast<D*>(pb);//pd2 is NULL
delete pb;
}

**reinterpret_cast:**可以在指针、引用、算术类型、函数指针或者成员指针和整数间进行相互转换,它只是将底层的比特模型重新解释成目标类型,不会对比特进行改变,所以是不安全的,只是为了故弄玄虚和其他目的。

class A {
    public:
    int m_a;
};
class B {
    public:
    int m_b;
};
class C : public A, public B {};
//那么对于以下代码:
C c;
printf("%p, %p, %p", &c, reinterpret_cast<B*>(&c), static_cast <B*>(&c));
//前两个的输出值是相同的,最后一个则会在原基础上偏移4个字节,这是因为static_cast计算了父子
//类指针转换的偏移量,并将之转换到正确的地址(c里面有m_a,m_b,转换为B*指针后指到m_b处),
//而reinterpret_cast却不会做这一层转换。

2、关于类类型的sizeof

① 问:定义一个空类型,没有成员变量和成员函数,它的sizeof是多少?

struct A{};

std::cout<<sizeof(A);

答:1,空类型的实例中不包含任何信息,本来求sizeof应该是0,但是当我们声明该类型的实例的时候,它必须在内存中占有一定空间,否则无法使用这些实例,至于占用多少内存,由编译器决定,Visual Studio每个空类型的实例占一个字节空间。
② 问:如果在类型中添加一个构造函数和一个析构函数,它的sizeof是多少?

struct A{
public:
  A(){}
  ~A(){}
};
std::cout<<sizeof(A);

答:和前面一样,是1,调用构造函数和析构函数只需要知道函数的地址即可,而这些函数的地址只与类型相关,而与类型的实例无关,编译器也不会因为这两个函数而在实例内添加任何额外信息。

③ 问:如果把析构函数标记为虚函数呢?

struct A{
public:
  A(){}
  virtual ~A(){}
};
std::cout<<sizeof(A);

答:是一个指针的大小(32位系统上是4,64位系统上是8)。C++编译器发现一个类型中有虚函数,就会为该类型生成虚表,并在该类型的每一个实例中添加一个指向虚表的指针(**注意:**只有一个指针,而不是每个虚函数一个指针,因为虚表是一个数组,只需要指向数组首元素,就可以遍历所有元素;**补充:**虚函数是为了实现多态而出现的,而虚函数的实现在C++中没有定义,实现方式由编译器决定,一般都是用虚表实现的,虚表存放的位置可参考vicness的专栏)。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
提供的源码资源涵盖了Java应用等多个领域,每个领域都包含了丰富的实例和项目。这些源码都是基于各自平台的最新技术和标准编写,确保了在对应环境下能够无缝运行。同时,源码中配备了详细的注释和文档,帮助用户快速理解代码结构和实现逻辑。 适用人群: 适合毕业设计、课程设计作业。这些源码资源特别适合大学生群体。无论你是计算机相关专业的学生,还是对其他领域编程感兴趣的学生,这些资源都能为你提供宝贵的学习和实践机会。通过学习和运行这些源码,你可以掌握各平台开发的基础知识,提升编程能力和项目实战经验。 使用场景及目标: 在学习阶段,你可以利用这些源码资源进行课程实践、课外项目或毕业设计。通过分析和运行源码,你将深入了解各平台开发的技术细节和最佳实践,逐步培养起自己的项目开发和问题解决能力。此外,在求职或创业过程中,具备跨平台开发能力的大学生将更具竞争力。 其他说明: 为了确保源码资源的可运行性和易用性,特别注意了以下几点:首先,每份源码都提供了详细的运行环境和依赖说明,确保用户能够轻松搭建起开发环境;其次,源码中的注释和文档都非常完善,方便用户快速上手和理解代码;最后,我会定期更新这些源码资源,以适应各平台技术的最新发展和市场需求。 所有源码均经过严格测试,可以直接运行,可以放心下载使用。有任何使用问题欢迎随时与博主沟通,第一时间进行解答!
提供的源码资源涵盖了小程序应用等多个领域,每个领域都包含了丰富的实例和项目。这些源码都是基于各自平台的最新技术和标准编写,确保了在对应环境下能够无缝运行。同时,源码中配备了详细的注释和文档,帮助用户快速理解代码结构和实现逻辑。 适用人群: 适合毕业设计、课程设计作业。这些源码资源特别适合大学生群体。无论你是计算机相关专业的学生,还是对其他领域编程感兴趣的学生,这些资源都能为你提供宝贵的学习和实践机会。通过学习和运行这些源码,你可以掌握各平台开发的基础知识,提升编程能力和项目实战经验。 使用场景及目标: 在学习阶段,你可以利用这些源码资源进行课程实践、课外项目或毕业设计。通过分析和运行源码,你将深入了解各平台开发的技术细节和最佳实践,逐步培养起自己的项目开发和问题解决能力。此外,在求职或创业过程中,具备跨平台开发能力的大学生将更具竞争力。 其他说明: 为了确保源码资源的可运行性和易用性,特别注意了以下几点:首先,每份源码都提供了详细的运行环境和依赖说明,确保用户能够轻松搭建起开发环境;其次,源码中的注释和文档都非常完善,方便用户快速上手和理解代码;最后,我会定期更新这些源码资源,以适应各平台技术的最新发展和市场需求。 所有源码均经过严格测试,可以直接运行,可以放心下载使用。有任何使用问题欢迎随时与博主沟通,第一时间进行解答!
提供的源码资源涵盖了Java应用等多个领域,每个领域都包含了丰富的实例和项目。这些源码都是基于各自平台的最新技术和标准编写,确保了在对应环境下能够无缝运行。同时,源码中配备了详细的注释和文档,帮助用户快速理解代码结构和实现逻辑。 适用人群: 适合毕业设计、课程设计作业。这些源码资源特别适合大学生群体。无论你是计算机相关专业的学生,还是对其他领域编程感兴趣的学生,这些资源都能为你提供宝贵的学习和实践机会。通过学习和运行这些源码,你可以掌握各平台开发的基础知识,提升编程能力和项目实战经验。 使用场景及目标: 在学习阶段,你可以利用这些源码资源进行课程实践、课外项目或毕业设计。通过分析和运行源码,你将深入了解各平台开发的技术细节和最佳实践,逐步培养起自己的项目开发和问题解决能力。此外,在求职或创业过程中,具备跨平台开发能力的大学生将更具竞争力。 其他说明: 为了确保源码资源的可运行性和易用性,特别注意了以下几点:首先,每份源码都提供了详细的运行环境和依赖说明,确保用户能够轻松搭建起开发环境;其次,源码中的注释和文档都非常完善,方便用户快速上手和理解代码;最后,我会定期更新这些源码资源,以适应各平台技术的最新发展和市场需求。 所有源码均经过严格测试,可以直接运行,可以放心下载使用。有任何使用问题欢迎随时与博主沟通,第一时间进行解答!

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值