C++的四种类型转换
c语言中提供的类型强转
int a = (int)b;
c++提供:
- const_cast:去掉常量属性的一个类型转换
int* p1 = (int*)&a;
int* p2 = const_cast<int*>(&a);
这两句是一样的,只不过使用第二种,可以保证类型转换是安全的,如果要转换成不符合的类型就会报错。
- static_cast:提供编译器认为安全的类型转换
int main()
{
//1
int a = 10;
char b = static_cast<int> (a);
//2
int* p = nullptr;
short* b = static_cast<short*>(p);
return 0;
}
对于第一种,int转char,编译器认为是安全的,就可以通过
对于第二章,int转成short,编译器认为类型转换无效
那么如果我一定要做这种类型转换呢?那么就是下面的reinterpret_cast
- reinterpret_cast:类似c风格的强制类型转换(不安全)
int *p = nullptr;
double* b = reinterpret_cast<double*>(p);
即使实际上这种转换并不安全,但也可以编译成功
- dynamic_cast:主要用在继承结构中,可以支持RTTI类型识别上下转换
示例代码:
#include<iostream>
using namespace std;
class Base {
public:
virtual void func() = 0;
};
class Derive1 :public Base
{
public:
virtual void func() { cout << "Derive -- 1" << endl; }
};
class Derive2 :public Base
{
public:
virtual void func() { cout << "Derive -- 2" << endl; }
};
void showFunc(Base* p)
{
p->func();//动态绑定
}
int main()
{
Derive1 d1;
Derive2 d2;
showFunc(&d1);
showFunc(&d2);
return 0;
//Derive -- 1
//Derive --
}
没有问题
但是随着软件开发的需求变更,要增加需求
在Derive2中添加一个函数
class Derive2 :public Base
{
public:
void func() { cout << "Derive -- 2" << endl; }
void showFunc{
cout << "new 2" << endl;
}
};
现在我要在showFunc中,其他的依旧动态绑定func()函数
而如果是Derive2对象,就要绑定新的showFunc()函数
使用
void showFunc(Base* p)
{
// dynamic_cast会检查p指针是否指向的是一个Derive2类型的对象。
//p->vfptr->vftable RTTI信息,如果是Derive2类型的对象
//转换类型成功---返回Derive2对象的地址给pd2;否则返回nullptr
Derive2* pd2 = dynamic_cast<Derive2*>(p);
if (pd2 != nullptr)
{
pd2->derive02func();
}
else {
p->func();//动态绑定
}
}
理解虚基类和虚继承
抽象类(有纯虚函数的类) / 虚基类
virtual
- 修饰成员方法是虚函数
- 可以修饰继承方式,是虚继承。被继承的类称为虚基类
#include<iostream>
using namespace std;
class A
{
public:
private:
int ma;
};
class B :virtual public A
{
public:
private:
int mb;
};
/*
A a:4字节 ma ---》4字节 ma
B b:8字节 ma,mb ---》12字节 vbptr, mb ,ma
*/
int main()
{
}
class A{}; sizeof(A) = 1
class B :public A{};sizeof(B) = 1;
class A {
virtual void fun(){};
};
class B :public A{};sizeof(B) = 4;//vfptr
class A {
virtual void fun(){};
};
class B :virtual public A{};sizeof(B) = 8;//vbptr + vfptr
基类指针指向派生类对象,永远指向的是派生类基类部分数据的起始地址
由于内存结构*p指向的是派生类基类部分数据的起始地址D8,但是vbptr和mb都还在前面,这时候delete p;就会导致前面的删不掉
菱形继承问题
多重继承:代码的复用 ---- 一派生类有多个基类
菱形继承问题
class D:public B,public C
{
};
一目了然:D中有两份来自不同父类的ma属性
尽量不要多重继承
实例代码:
#include<iostream>
using namespace std;
class A
{
public:
A(int data) :ma(data) { cout << "A()" << endl; }
~A() { cout << "~A()" << endl; }
protected:
int ma;
};
//===================================================
class B : public A
{
public:
B(int data) :A(data), mb(data) { cout << "B()" << endl; }
~B() { cout << "~B()" << endl; }
protected:
int mb;
};
class C : public A
{
public:
C(int data) :A(data), mc(data) { cout << "C()" << endl; }
~C() { cout << "~C()" << endl; }
protected:
int mc;
};
//===================================================
class D : public B,public C
{
public:
D(int data):B(data), C(data),md(data) { cout << "D()" << endl; }
~D() { cout << "~D()" << endl; }
protected:
int md;
};
int main()
{
D d(10);
}
d的内存布局 ---- 占20字节
打印结果:
此时只要在B,C中对A采用虚继承,就可以了。内存结构如下
注意:此时需要在D中加入A的构造,即使从继承类看,他并没有直接继承A。但是由于B,C都是虚继承,此时A的构造就要定位到D中对A进行构造;
具体如下:
class D : public B,public C
{
public:
D(int data):A(data),B(data), C(data),md(data) { cout << "D()" << endl; }
~D() { cout << "~D()" << endl; }
protected:
int md;
};
标签:cout,int,基础,c++,class,cast,data,public,施磊
From: https://blog.csdn.net/fcopy/article/details/143063467