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

一、隐式转换

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

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

  1. int ival = 3;  
  2. double dval = 3.1415  
  3. ival + dval; //ival 被提升为double 类型:3.0 

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

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

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

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

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

  1. double difference(int ival1, int ival2)  
  2. {  
  3. return ival1 - ival2; //返回值被提升为double 类型.  

* 条件表达式转bool类型

  1. int iVal;
  2. if (iVal){}

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

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

  1. void dosomething(A aObject);  
  2. class A {  
  3. public:  
  4. A(int x = 0);  
  5. }  
  6. 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);

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值