01 虚基类和虚继承
多重继承 :代码的复用 一个派生类有多个基类
class C: public A, public B
{
};
抽象类(有纯虚函数的类) / 虚基类 被虚继承的类称作虚基类 vbptr和vbtable
virtual
1.修饰成员方法是虚函数
2.可以修饰继承方式,是虚继承。被虚继承的类,称作虚基类
class A
{
public:
virtual void func() { cout << "call A::func" << endl; }
void operator delete(void *ptr)
{
cout << "operator delete p:" << ptr << endl;
free(ptr);
}
private:
int ma;
};
class B : virtual public A
{
public:
void func() { cout << "call B::func" << endl; }
void* operator new(size_t size)
{
void *p = malloc(size);
cout << "operator new p:" << p << endl;
return p;
}
private:
int mb;
};
/*
A a; 4个字节
B b; ma,mb 8个字节+4=12个字节 vbptr
*/
int main()
{
// 基类指针指向派生类对象,永远指向的是派生类基类部分数据的起始地址
B b;
A *p = &b;//new B(); // B::vftable
cout << "main p:" << p << endl;
p->func();
//delete p;
return 0;
}
02 菱形继承
C++的多重继承 - 菱形继承的问题 派生类有多份间接基类的数据 设计的问题
好处,可以做更多代码的复用 D -> B,C B *p = new D() C *p = new D()
class A
{
public:
A(int data) :ma(data) { cout << "A()" << endl; }
~A() { cout << "~A()" << endl; }
protected:
int ma;
};
//=======================================
class B : virtual public A
{
public:
B(int data) :A(data), mb(data) { cout << "B()" << endl; }
~B() { cout << "~B()" << endl; }
protected:
int mb;
};
class C : virtual 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:
//“A::A”: 没有合适的默认构造函数可用
D(int data) :A(data), B(data), C(data), md(data) { cout << "D()" << endl; }
~D() { cout << "~D()" << endl; }
protected:
int md;
};
int main()
{
D d(10);
return 0;
}
03 C++四种类型转换
C++语言级别提供的四种类型转换方式
int a = (int)b;
const_cast : 去掉(指针或者引用)常量属性的一个类型转换
static_cast : 提供编译器认为安全的类型转换(没有任何联系的类型之间的转换就被否定了)
reinterpret_cast : 类似于C风格的强制类型转换
dynamic_cast : 主要用在继承结构中,可以支持RTTI类型识别的上下转换
class Base
{
public:
virtual void func() = 0;
};
class Derive1 : public Base
{
public:
void func() { cout << "call Derive1::func" << endl; }
};
class Derive2 : public Base
{
public:
void func() { cout << "call Derive2::func" << endl; }
// Derive2实现新功能的API接口函数
void derive02func()
{
cout << "call Derive2::derive02func" << endl;
}
};
/*
typeid(*p).name() == "Derive"
*/
void showFunc(Base *p)
{
// dynamic_cast会检查p指针是否指向的是一个Derive2类型的对象?
// p->vfptr->vftable RTTI信息 如果是,dynamic_cast转换类型成功,
// 返回Derive2对象的地址,给pd2;否则返回nullptr
// static_cast编译时期的类型转换 dynamic_cast运行时期的类型转换 支持RTTI信息识别
Derive2 *pd2 = dynamic_cast<Derive2*>(p);
if (pd2 != nullptr)
{
pd2->derive02func();
}
else
{
p->func(); // 动态绑定 *p的类型 Derive2 derive02func
}
}
int main()
{
Derive1 d1;
Derive2 d2;
showFunc(&d1);
showFunc(&d2);
//static_cast 基类类型 《=》 派生类类型 能不能用static_cast?当然可以!
//int *p = nullptr;
//double* b = reinterpret_cast<double*>(p);
//const int a = 10;
//int *p1 = (int*)&a;
//int *p2 = const_cast<int*>(&a);
// const_cast<这里面必须是指针或者引用类型 int* int&>
//int b = const_cast<int>(a);
return 0;
}