6.类和对象_继承
//继承是面向对象三大特性之一
//语法:class 子类 : 继承方式 父类
//子类也叫派生类,父类也叫基类
//继承方式有三种:公共继承、保护继承、私有继承
//公共继承:原来public和protected关系不变
//保护继承:public和protected全变成protected
//私有继承:public和protected全变成private
//
//继承中的对象模型
//父类中所有非静态的成员属性,都会被子类继承
//父类中私有的成员属性被编译器隐藏,因此访问不到,但是确实被继承
//(利用开发人员命令提示工具查看对象模型)cl /d1 reportSingleClassLayout类名 文件名
//继承中构造和析构的顺序
//先构造父类后构造子类
//先析构子类再析构父类
//继承同名成员处理方式
//访问子类同名成员 直接访问
//访问父类同名成员 加作用域
//如果子类出现和父类同名成员函数,会隐藏掉父类中所用同名成员函数(包括重载),同理需要加作用域访问
//同名静态成员处理方式相同
//
//多继承语法
//class 子类 : 继承方式 父类1, 继承方式 父类2, ...
//同名成员访问方式相同
//实际开发不建议使用
//
//菱形继承
//两个派生类继承同一个基类,又有某个类同时继承两个派生类
//菱形继承导致这个基类的数据到后面这个类的数据有两份,其实只需要一份,资源浪费
//利用虚继承解决菱形继承问题
#include <iostream>
#include <string>
using namespace std;
class BasePage
{
public:
void header()
{
cout << "PUBLIC HEADER" << endl;
}
void footer()
{
cout << "PUBLIC FOOTER" << endl;
}
};
class Java : public BasePage
{
public:
void content()
{
cout << "JAVE CONTENT" << endl;
}
};
void test01()
{
Java ja;
ja.header();
ja.footer();
ja.content();
}
//同名成员处理
class Base
{
public:
int m_A;
Base() :m_A(100) {}
};
class Son : public Base
{
public:
int m_A;
Son() : m_A(200) {}
};
void test02()
{
Son s;
cout << "s.m_A = " << s.m_A << endl;
cout << "s.Base::m_A=" << s.Base::m_A << endl;
}
//菱形继承
class AllBase
{
public:
int m_A;
};
//继承方式前加入virtual变为虚继承,AllBase称为虚基类
class Son1 :virtual public AllBase {};
class Son2 :virtual public AllBase {};
class Grandson :public Son1, public Son2 {}; //只需要一份m_A
/*
class Grandson size(12):
+---
0 | +--- (base class Son1)
0 | | {vbptr}
| +---
4 | +--- (base class Son2)
4 | | {vbptr}
| +---
+---
+--- (virtual base AllBase)
8 | m_A
+---
*/
//vbptr 虚基类指针
//v - virtual b - base ptr - pointer
//指向vbtable(虚基类表)
/*
Grandson::$vbtable@Son1@:
0 | 0
1 | 8 (Grandsond(Son1+0)AllBase)
Grandson::$vbtable@Son2@:
0 | 0
1 | 4 (Grandsond(Son2+0)AllBase)
vbi: class offset o.vbptr o.vbte fVtorDisp
AllBase 8 0 4 0
*/
//表格中记录的是地址的偏移量
//即vbptr+偏移量=&m_A
void test03()
{
Grandson gs;
gs.Son1::m_A = 18;
gs.Son2::m_A = 28;
cout << "gs.Son1::m_A=" << gs.Son1::m_A << endl;
cout << "gs.Son2::m_A=" << gs.Son2::m_A << endl;
cout << "gs.m_A=" << gs.m_A << endl;
}
int main()
{
//test02();
test03();
system("pause");
return 0;
}