前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >C++补充知识&C++11及其特性

C++补充知识&C++11及其特性

作者头像
半生瓜的blog
发布2023-05-12 21:45:03
4020
发布2023-05-12 21:45:03
举报
文章被收录于专栏:半生瓜のblog

C++补充知识&C++11及其特性

explicit关键字

加在类构造函数前表明该构造函数是显式的,并非隐式的,不能进行隐式类型转换!

类构造函数默认情况下声明为隐式。

给构造函数加上关键字explicit使得该类创建对象必须显式调用构造。

代码语言:javascript
复制
student xiaohua(18);//显式构造
student xiaoming = 18;//隐式构造
student xiaoli("小李",18);//显式构造
student xiaomei = ("小美",18);//隐式构造-C++11之前编译不能过
//初始化参数列表C++11新增

看到=要想是赋值呢,还是隐式构造呢。

左值和右值的概念

按字面意思,通俗的说,以赋值运算符=为界,左边的就是左值,右边的就是右值。

左值(lvalue)——代表一个在内存中占有确定位置的对象(就是有一个地址)。

右值(rvalue)——通过排他性来定义,每个表达式不是左值就是右值,rvalue是不在内存中占有确定位置的表达式,而是在存在寄存器中。

所有的左值(无论是数组,函数或不完全类型)都可以转化成右值。

函数返回值当引用

C++使用引用时的难点

  1. 当函数返回值为引用时 若返回栈变量,不能称为其他引用的初始值,不能作为左值使用。 (函数在栈上开辟空间存放形参和局部变量,这个变量所在内存空格占的位置不是固定的,再有一个函数压进栈来,原来的局部变量所在内存被覆盖。(变量和其对应的地址对不上了,该变量指向的那个地址所存的内容被覆盖了)-个人理解)
  2. 若返回静态变量或全局变量 可以成为其他引用的初始值。 即可作为右值使用,也可以作为左值使用。
  3. 返回形参当引用 (注:C++链式编程中,经常用到引用, 例如运输符重载)

Array容器

详见-C++SLT容器中。

(取容器中元素的地址貌似是没有意义的,除非他里面的内容不在改变,因为有的容器中元素发生变化后,里面的容器元素是会发生移动的。)

其中,有意思的是empty()接口永远false,因为在构造的时候要指定数量。

C++类型转换

C语言风格

代码语言:javascript
复制
double PI = 3.1415926;

int i = PI;//隐式类型转换

int i1 = (int)PI;//显式类型转换
int* addr = (int*)0x888888;//强制类型转换,整数直接指针

C++类型转换操作符

static_cast

静态类型转换,同时做检查给予提示。

代码语言:javascript
复制
int i = static_cast<int>(PI);
 
//父子类之间的类型转换
Dog* dog = new Dog;
//子类指针转型到父类指针
Animal* animal = static_cast<Animal*>(dog);
//父类指针转型到子类指针
Dog* dog2 = static_cast<Dog*>(animal);
Dog dog2;
//子类引用转型到父类引用
Animal& animal2 = static_cast<Animal&>(dog2);

//基本类型转换
int kk = 234;
char cc = static_cast<char>(kk);//都是模板

//把空指针转换成目标类型的空指针
int* p = static_cast<int*>(NULL);
Dog* dp = static_cast<Dog*>(NULL);

//把任何类型的表达式转化成void类型
int* p = new int[10];
void* vp = static_cast<void*>(p);
vp = p;//效果相同 

主要用法:

  • 用于类层次结构中基类(父类)和派生类(子类)之间指针或引用的转换。上行指针或引用(派生类到基类)转换安全,下行不安全
  • 用于基本数据类型之间的转换,如把int转换成char,把int转换成enum。这种转换的安全性也要开发人员来保证。
  • 把空指针转换成目标类型的空指针。
  • 把任何类型的表达式转换成void类型。

(写了会提醒编译器检查,提醒其他程序员要注意。)

(没事别转。)

reinterpret_cast

(可以用于强制类型转换)

重新解释类型不同类型间的互转,数值与指针间的互转。

用法: TYPE b = reinterpret_cast < TYPE> (a)

TYPE必须是一个指针、引用、算术类型、函数指针.

代码语言:javascript
复制
int* p = reinterpret_cast<int*>(0x999999);//整型转指针
int* val = reinterpret_cast<int>(p);//指针转整型

Dog  dog1;
Animal* a1 = &dog1;

Animal& a2 = dog1;
Dog& dog3 = reinterpret_cast<Dog&>(a2);//引用强转用法

注意:滥用 reinterpret_cast 运算符可能很容易带来风险。 除非所需转换本身是低级别的,否则应使用其他强制转换运算符之一。(低级别:在内存没啥差别)

与static_cast相加可替换掉C风格的类型转换。

dynamic_cast

动态类型转换

将一个基类对象指针cast到继承类指针,dynamic_cast 会根据基类指针是否真正指向继承类指针来做相应处理。失败返回null,成功返回正常cast后的对象指针。

( 看该父类是否真正指向该子类(因为有多个子类。))

(子类* xx = dynamic_cast<子类*>(父类xx);

将一个基类对象引用cast 继承类对象,dynamic_cast 会根据基类对象是否真正属于继承类来做相应处理。失败抛出异常bad_cast。

代码语言:javascript
复制
void animalPlay(Animal* animal) {
	animal->cry();

	Dog* pDog = dynamic_cast<Dog*>(animal);
	if (pDog) {
		pDog->play();
	}
	else {//pDog == NULL
		cout << "不是狗,别骗我!" << endl;
	}

	Cat* pCat = dynamic_cast<Cat*>(animal);
	if (pCat) {
		pCat->play();
	}
	else {//pDog == NULL
		cout << "不是猫,别骗我!" << endl;
	}
}
代码语言:javascript
复制
void animalPlay(Animal& animal) {
	animal.cry();

	try {
		Dog& pDog = dynamic_cast<Dog&>(animal);
		pDog.play();
	}
	catch (std::bad_cast bc) {
		cout << "不是狗,那应该是猫" << endl;
	}

	try {
		Cat& pCat = dynamic_cast<Cat&>(animal);
		pCat.play();
	}
	catch (std::bad_cast bc) {
		cout << "不是猫,那应该是上面的狗" << endl;
	}

注意: dynamic_cast在将父类cast到子类时,父类必须要有虚函数一起玩。

const_cast

去掉const属性,仅针对于指针和引用。

代码语言:javascript
复制
void demo(const char p)
{
    //对指针去掉const 重新赋值
    char* p1 = const_cast<char*>(p);

    //直接去掉const修改
    const_cast<char*>(P)[0] = 'a';
}

常量字符串不行,考虑内存范围。

在去掉常量限定符之前,保证指针所指向的内存可被修改,不能修改则会引起异常。

类型转换使用建议

  1. static_cast静态类型转换,编译的时c++编译器会做编译时的类型检查;隐式转换;基本类型转换,父子类之间合理转换
  2. 若不同类型之间,进行强制类型转换,用reinterpret_cast<>() 进行重新解释。 建议:

C语言中 能隐式类型转换的,在c++中可用 static_cast<>()进行类型转换。因C++编译器在编译检查一般都能通过;C语言中不能隐式类型转换的,在c++中可以用 reinterpret_cast<>() 进行强制类型解释**。

总结:static_cast<>()和reinterpret_cast<>() 基本上把C语言中的 强制类型转换给覆盖,注意reinterpret_cast<>()很难保证移植性。

3.dynamic_cast<>(),动态类型转换,安全的虚基类和子类之间转换;运行时类型检查

4.const_cast<>(),去除变量的只读属性


程序员必须清楚的知道: 要转的变量,类型转换前是什么类型,类型转换后是什么类型,转换后有什么后果。

一般情况下,不建议进行类型转换;避免进行类型转换。


本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2021-10-01,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • C++补充知识&C++11及其特性
    • explicit关键字
      • 左值和右值的概念
        • 函数返回值当引用
          • Array容器
            • C++类型转换
              • static_cast
              • reinterpret_cast
              • dynamic_cast
              • const_cast
              • 类型转换使用建议
          相关产品与服务
          容器服务
          腾讯云容器服务(Tencent Kubernetes Engine, TKE)基于原生 kubernetes 提供以容器为核心的、高度可扩展的高性能容器管理服务,覆盖 Serverless、边缘计算、分布式云等多种业务部署场景,业内首创单个集群兼容多种计算节点的容器资源管理模式。同时产品作为云原生 Finops 领先布道者,主导开源项目Crane,全面助力客户实现资源优化、成本控制。
          领券
          问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档