这又是一个好话题,所谓转换就是把a变成b。隐式转换就是说在我们没有主动的去转换的地方发生的转换,显示当然就是我们主动的去转换。
隐式转换:系统跟据程序的需要而自动转换
class CTest
{
public:
CTest(int i)
{
qDebug() << "Test Constructor";
m_nValue = i;
}
void print()
{
qDebug() << "Test print value: " << m_nValue;
}
private:
int m_nValue;
};
void printTest(CTest test)
{
test.print();
}
int main(int argc, char *argv[])
{
QApplication app(argc, argv);
// 1、赋值式的隐式转换
int a = 5;
float b = a; // a、赋值时,a隐式的转成了float类型
double c = a + b; // b、赋值时,a和b都隐式的转成了double类型
// 类型的还有,传参,返回值时。
qDebug() << c;
// 2、对象类的隐式转换,20转换为GTest对象
printTest(20);
return app.exec();
}
运行结果:
10
Test Constructor
Test print value: 20
显式转换:又叫强制转换,代码中明确写明的转换
class CParent
{
public:
virtual ~CParent(){}
virtual void print()
{
qDebug() << "print CParent";
}
};
class CChild : public CParent
{
public:
virtual void print() override
{
qDebug() << "print CChild";
}
};
class CTest1
{
public:
CTest1(){}
~CTest1(){}
void print()
{
qDebug() << "print CTest1";
}
};
class CTest2 : public CTest1
{
public:
CTest2(){}
~CTest2(){}
void print()
{
qDebug() << "print CTest2";
}
};
int main(int argc, char *argv[])
{
QApplication app(argc, argv);
// 1、赋值式的显式转换
int a = 5;
float b = (float)a;
CChild *pChild = new CChild();
// 2、static_cast : 静态转换,强制把一个类型转换为另一个类型,而不去检查运行时。
CParent *pParent1 = static_cast<CParent*>(pChild);
pParent1->print();
// 3、dynamic_cast : 动态转换,强制把一个类型转换为另一个类型,会检查是否可以转换。依赖运行时态RTTI,
// 本质上是依赖虚函数表,虚表需要类中至少含有一个虚函数才能正常使用。
CParent *pParent2 = dynamic_cast<CParent*>(pChild);
pParent2->print();
// 但是我用Qt和用vs2019,下面的代码都可以运行。运行时不会出错。打印为CTest1结果也是合理的。
CTest2 *pTest = new CTest2();
CTest1 *pTest1 = dynamic_cast<CTest1*>(pTest);
pTest1->print();
// 4、const_cast : 和const的属性相关,
const int c_a = 10;
const int *p = &c_a;
// a、将const指针转为非Const类型,常用,因为不能把一个const变量直接赋给一个非const变量
int *p1 = const_cast<int*>(p);
// b、将非const指针转为Const类型,实际中我没用过。
const int *p2 = const_cast<const int*>(p1);
// 5、reinterpret_cast : 跨越类别的转换,主要用于从指针A转换到指针B
int *pReiter = &a;
char* pC1 = reinterpret_cast<char*>(pReiter);
qDebug() << &pC1 << " : " << pC1 << " : " << *pC1;
int* pC2 = reinterpret_cast<int*>(pC1);
qDebug() << &pC2 << " : " << pC2 << " : " << *pC2;
qDebug() <<&a;
return app.exec();
}
运行结果:
print CChild
print CChild
print CTest1
0x73fc70 : A : A
0x73fc68 : 0x73fc7c : 65
0x73fc7c
从上归纳得到:
1、static_cast、dynamic_cast :用于父子关系的转换。dynamic_cast慢一些,但更安全。
2、const_cast :用于处理const属性
3、reinterpret_cast :用于跨越类别的转换,指针转换为整型,整型转换为指针,指针类型A转换为指针类型B。
RTTI讲解
class Point
{
public:
Point( float xval );
virtual ~Point();
float x() const;
static int PointCount();
protected:
virtual ostream& print( ostream &os ) const;
float _x;
static int _point_count;
};
以上类的内存中模型:
2011030621295291.jpg
1、对象的内存是Point pt ,包含内内成员变量和虚函数表的地址
2、虚表的第一项是type_info for Point 里面包含 RTTI Info
type_info for Point 的数据如下:
2011030622331269.jpg
虚表上面的地址是指向一个结构 Derive::`RTTI Complete Object Locator , 这个结构指向该类的名字,和其对象继承链。