C++类型强制转换:隐式转换和显式转换(包含Qt智能指针类型转换)

简介: C++类型强制转换:隐式转换和显式转换(包含Qt智能指针类型转换)

一、隐式转换


C++隐式转换发生在以下几种情况下


* 在混合类型的算术表达式中


int ival = 3;  

double dval = 3.1415  

ival + dval; //ival 被提升为double 类型:3.0

* 初始化,用一种类型的表达式赋值


int *pi = NULL; // NULL(0)被转换成了int* 类型的空指针值

int iVap = 3.14;

* 用一个表达式传递给一个函数调用


extern double sqrt(double);  

sqrt(2); //2被提升为double类型: 2.0

* 从一个函数返回一个表达式


double difference(int ival1, int ival2)  

{  

return ival1 - ival2; //返回值被提升为double 类型.  

}

* 条件表达式转bool类型


int iVal;

if (iVal){}

* C++内建类型(char,int,short,double etc.)对像之间默认含有隐式转换


* C++用户定义类对象之间可以含有C++隐式转换.


void dosomething(A aObject);  

class A {  

public:  

A(int x = 0);  

}  

dosomething(20); // Ok 隐式转换

*C++类对象的向上隐式转换(向上转型,即下级向上级转换,将派生类对象赋值给基类)


class Base{ };


class Derived : public base{ };


Base* Bptr;


Derived* Dptr;


Bptr = Dptr; //编译正确,允许隐式向上类型转换


Dptr = Bptr;//编译错误,C++不允许隐式的向下转型;



二、显示转换(普通指针)


C++有四大强制类型转换符:reinterpret_cast, const_cast, static_cast, dynamic_cast.


使用形式为:cast-name<type>(expression)


1、静态转换(static_cast)

static_cast包含的转换类型有典型的非强制变换、窄化(有信息丢失)变换、使用void*的强制转换、类对象的向下显示转换。

(1)典型的非强制变换:

从窄类型向宽类型的转换,如char向short int,int,long int,float,double,long double的转换。

char a = 1;

long b = static_cast<long>(a);

(2)窄化变换:

与第1种相反,从宽类型向窄类型的变换。

long b = 1;

char a = static_cast<char>(b);

(3)使用void*的强制变换:

struct callback_param

{

   void *vp;

};


int a = 1;

struct callback_param cp;

cp.vp = &a;      //编译器允许从任意类型指针向void*转换

int *ip = static_cast<int *>(cp.vp);

(4)类层次的转换

进行向下类型转换(上级向下级转换,基类向派生类转换)


class Base{ };


class Derived : public base{ };


Base* B;


Derived* D;


D = static_cast<Drived*>(B); //正确,通过使用static_cast向下转型




2、常量转换(const_cast)

从const转换为非const,从volatile转换为非volatile。取得const对象的地址,会生成一个指向const的指针,volatile同。

const int i = 0;

int *ip = const_cast<int *>(&i);

volatile int a = 0;

int *ap = const_cast<int *>(&a);

3、重解释转换(reinterpret_cast)

最不安全的一种转换机制,将对象转变为完全不同类型的对象,这是低级的位操作。

struct msg_hdr

{

   int msg_type;

   int msg_len;

   char msg_data[0];

};


struct msg_data

{

   int data1;

   int data2;

};


struct msg_hdr *p = reinterpret_cast<struct msg_hdr *>(recvbuf);

struct msg_data *pdata = reinterpret_cast<struct msg_data *>(p->msg_data);

4、动态转换(dynamic_cast)


和static_cast不同,dynamic_cast涉及运行时的类型检查。如果向下转型是安全的(也就是说,如果基类指针或者引用确实指向一个派生类的对象),这个运算符会传回转型过的指针。如果向下转型不安全(即基类指针或者引用没有指向一个派生类的对象),这个运算符会传回空指针。就是说,类层次的向下转换(基类向派生类转换),转换过程中会通过RTTI检查转换类型是否正常,不正常将返回空。


dynamic_cast使用有几个前提:


(1)type必须是类的指针、类的引用,或者void*


(2)必须要有虚函数表,也就是说如果要进行类的类型转换,则必须是定义了虚函数的类。即要使用dynamic_cast类中必须定义虚函数。

#include <iostream>

using namespace std;


class pet

{

   public:

   virtual ~pet()

   {

   }

};


class dog : public pet

{

};


class cat : public pet

{

};


int main(void)

{

   pet *b = new cat;


   dog *d1 = dynamic_cast<dog *>(b);

   cat *d2 = dynamic_cast<cat *>(b);


   cout << "d1 = " << (long)d1 << endl;  // d1 = 0

   cout << "d2 = " << (long)d2 << endl;

}



三、显式转换(智能指针)


1、标准C++


std::static_pointer_cast,


std::dynamic_pointer_cast,


std::const_pointer_cast,


std::reinterpret_pointer_cast


2、Qt的智能指针类型转换


qSharedPointerCast


qSharedPointerDynamicCast


qSharedPointerConstCast


qWeakPointerCast


例如:


QSharedPointer<REntity> ent = m_pStorage->queryEntity(*iter2);


QSharedPointer<RCircleEntity> cir = qSharedPointerCast<RCircleEntity>(ent);



相关文章
|
8天前
|
存储 编译器 Linux
【c++】类和对象(上)(类的定义格式、访问限定符、类域、类的实例化、对象的内存大小、this指针)
本文介绍了C++中的类和对象,包括类的概念、定义格式、访问限定符、类域、对象的创建及内存大小、以及this指针。通过示例代码详细解释了类的定义、成员函数和成员变量的作用,以及如何使用访问限定符控制成员的访问权限。此外,还讨论了对象的内存分配规则和this指针的使用场景,帮助读者深入理解面向对象编程的核心概念。
27 4
|
23天前
|
存储 安全 编译器
在 C++中,引用和指针的区别
在C++中,引用和指针都是用于间接访问对象的工具,但它们有显著区别。引用是对象的别名,必须在定义时初始化且不可重新绑定;指针是一个变量,可以指向不同对象,也可为空。引用更安全,指针更灵活。
|
1月前
|
存储 C++
c++的指针完整教程
本文提供了一个全面的C++指针教程,包括指针的声明与初始化、访问指针指向的值、指针运算、指针与函数的关系、动态内存分配,以及不同类型指针(如一级指针、二级指针、整型指针、字符指针、数组指针、函数指针、成员指针、void指针)的介绍,还提到了不同位数机器上指针大小的差异。
38 1
|
1月前
|
存储 编译器 C语言
C++入门2——类与对象1(类的定义和this指针)
C++入门2——类与对象1(类的定义和this指针)
29 2
|
1月前
|
存储 编译器 程序员
C++类型参数化
【10月更文挑战第1天】在 C++ 中,模板是实现类型参数化的主要工具,用于编写能处理多种数据类型的代码。模板分为函数模板和类模板。函数模板以 `template` 关键字定义,允许使用任意类型参数 `T`,并在调用时自动推导具体类型。类模板则定义泛型类,如动态数组,可在实例化时指定具体类型。模板还支持特化,为特定类型提供定制实现。模板在编译时实例化,需放置在头文件中以确保编译器可见。
32 11
|
1月前
|
存储 安全 编译器
【C++】C++特性揭秘:引用与内联函数 | auto关键字与for循环 | 指针空值(一)
【C++】C++特性揭秘:引用与内联函数 | auto关键字与for循环 | 指针空值
|
1月前
|
C语言 C++
【C语言】指针篇-一篇搞定不同类型指针变量-必读指南(3/5)
【C语言】指针篇-一篇搞定不同类型指针变量-必读指南(3/5)
|
1月前
|
存储 C++ 索引
C++函数指针详解
【10月更文挑战第3天】本文介绍了C++中的函数指针概念、定义与应用。函数指针是一种指向函数的特殊指针,其类型取决于函数的返回值与参数类型。定义函数指针需指定返回类型和参数列表,如 `int (*funcPtr)(int, int);`。通过赋值函数名给指针,即可调用该函数,支持两种调用格式:`(*funcPtr)(参数)` 和 `funcPtr(参数)`。函数指针还可作为参数传递给其他函数,增强程序灵活性。此外,也可创建函数指针数组,存储多个函数指针。
|
2月前
|
编译器 C++
【C++核心】指针和引用案例详解
这篇文章详细讲解了C++中指针和引用的概念、使用场景和操作技巧,包括指针的定义、指针与数组、指针与函数的关系,以及引用的基本使用、注意事项和作为函数参数和返回值的用法。
37 3
|
1月前
|
存储 编译器 程序员
【C++】C++特性揭秘:引用与内联函数 | auto关键字与for循环 | 指针空值(二)
【C++】C++特性揭秘:引用与内联函数 | auto关键字与for循环 | 指针空值