继承好处: 减少重复的代码 语法: class 子类(派生类):继承方式 父类(基类) 继承方式: 公共继承,保护继承,私有继承
代码语言:javascript复制#include<iostream>
using namespace std;
/*
class baise
{
public:
int ma;
protected:
int mb;
private:
int mc;
};
//定义一个父类,里面有3种
//儿子以公共方式继承父类
class son :public baise
{
//注意:
//父类中所有非静态成员属性会被子类继承下去
//父类中私有成员属性是被编译器·隐藏起来了,但是确实是被继承下来了
int mb;
void fun()
{
ma = 100; // 父类公共内容 以公共继承方式,类内 类外可以访问,也是公共权限
mb = 100; // 父类保护内容 以公共继承方式,类内可以访问,类外不能访问,也是保护权限
//mc = 100;父类的私有内容,以公共继承方式,访问不到
}
};
void test01()
{
son s1;
s1.ma = 100;
//s1.mb = 100; 保护权限,类外不能访问
cout << sizeof(s1) << endl;
}
//以保护权限来继承父类
代码语言:javascript复制class son2 :protected baise
{
void func()
{
ma = 100;//父类公共内容 以保护继承方式,类内可以访问,类外不能,是保护权限
mb = 100; //父类保护内容 以保护继承方式,类内可以访问,类外不能,是保护权限
//mc = 100;父类的私有内容,以保护继承方式,访问不到
}
};
void test02()
{
son2 s2;
//以保护权限继承,类外都不能访问
/*s2.ma = 100;
* s2.mb=100;
*/
/*
}
//以私有权限继承父类
class son3 :private baise
{
void func()
{
ma = 100;//父类公共内容 以私有继承方式,类内可以访问,类外不能,是私有权限
mb = 100; //父类保护内容 以私有继承方式,类内可以访问,类外不能,是私有权限
//mc = 100;父类的私有内容,以保护继承方式,访问不到
}
};
void test03()
{
son3 s3;
//s2.ma = 100;
//s2.mb=100;
}
*/
//继承中同名成员处理
代码语言:javascript复制class base
{
public:
base()
{
ma = 100;
}
int ma;
};
class sonn :public base
{
public:
sonn()
{
ma = 10;
}
int ma;
};
//同名成员
void testt()
{
sonn s;
cout << "子类中的成员.访问" << s.ma << endl;
cout << "父类中的成员base::作用域访问" << s.base::ma << endl;
}
//同名函数
- 如果子类中没有,只有父类中有,直接调用会调用父类中的函数
- 直接调用,调用的·是子类中同名的成员
- 如果子类中出现与父类同名的成员函数,会隐藏掉父类中所有同名的函数,除非加上作用域
- 总结:
- 子类对象可以直接访问到子类中的同名成员
- 子类对象加作用域可以访问到父类中同名的成员
- 当子类和父类有同名的成员函数时,子类会隐藏父类中同名成员函数,,加作用域可以访问到父类中同名的函数
//同名静态成员处理 //同名静态成员属性
代码语言:javascript复制class person
{
public:
static int ma;
static void func()
{
cout << "person的成员函数的调用" << endl;
}
static void func(int a)
{
cout << "person(int a)的成员函数的调用" << endl;
}
};
int person::ma = 100;
class personson :public person
{
public:
static int ma;
static void func()
{
cout << "personson的成员函数的调用" << endl;
}
};
int personson::ma = 200;
void test01()
{
//1.通过对象访问
cout << "1.通过对象访问" << endl;
personson p; //实例化
cout <<"personson下:"<< p.ma << endl;
cout << "person下"<<p.person::ma << endl;
//2.通过类名访问
cout << "2.通过类名访问" << endl;
//第一个::代表通过类名方式访问
//第二个::代表访问父类作用域下
cout<<"person下"<< personson::person::ma << endl;
cout<<"personson下" << personson::ma << endl;
}
//同名静态成员函数
代码语言:javascript复制void test02()
{
//通过对象访问
personson p;
p.func();
p.person::func();
//通过类名方式访问
personson::person::func();
personson::func();
//错误personson::func(10); 在personson下没有类似void func(int a)的函数
personson::person::func(10);
}
//多继承语法 语法:class 子类:继承方式 父类1,继承方式 父类2,…
- 多继承中如果父类中出现了同名的情况,子类中使用的时候要加作用域来区分
class base1
{
public:
base1()
{
ma = 100;
}
int ma;
};
class base2
{
public:
base2()
{
mb = 200;
ma = 200;
}
int mb;
int ma;
};
//现在要有一个子类,来继承base1 base2
代码语言:javascript复制class base3 :public base1, public base2
{
public:
base3()
{
mc = 300;
md = 400;
}
int mc;
int md;
};
void test03()
{
base3 b;
cout << sizeof(b) << endl;
//错误-》因为名字重复要用作用域加以区分cout << b.ma << endl;
cout << "base1下" << b.base1::ma << endl;
cout << "base2下" << b.base2::ma << endl;
}
//利用虚继承可以解决 菱形继承问题 //主要带来问题是子类继承两份相同的数据,导致资源浪费以及毫无意义
代码语言:javascript复制class animal
{
public:
int age;
};
//加入virtual后变成虚继承,animal叫虚基类
//从而统一
class monkey:virtual public animal{};
class xingxing:virtual public animal{};
//不管猴子还是猩猩,都是动物,所以虚继承animal类
class persons:public monkey,public xingxing{};
/*
* 对象模型:
* class persons size(8):
---
0 | --- (base class monkey)
0 | | --- (base class animal)
0 | | | age
| | ---
| ---
4 | --- (base class xingxing)
4 | | --- (base class animal)
4 | | | age
| | ---
| ---
---
*/
//虚继承之后对象模型:
/*
* class persons size(12):
---
0 | --- (base class monkey)
0 | | {vbptr}
| ---
4 | --- (base class xingxing)
4 | | {vbptr}
| ---
---
--- (virtual base animal)
8 | age
---
persons::$vbtable@monkey@:
0 | 0
1 | 8 (personsd(monkey 0)animal)
persons::$vbtable@xingxing@:
0 | 0
1 | 4 (personsd(xingxing 0)animal)
vbi: class offset o.vbptr o.vbte fVtorDisp
animal 8 0 4 0
*/
/*
- 解释:
- vbptr 虚基类指针
- v代表 virtual
- b 代表 base
- ptr 代表 pointer
- 8 | age
- 0 | ±-- (base class monkey) 0 | | {vbptr} persons::$vbtable@monkey@: 0 | 0 1 | 8 (personsd(monkey 0)animal)
偏移量是8 0 8=8
4 | ±-- (base class xingxing) 4 | | {vbptr} persons::$vbtable@xingxing@: 0 | 0 1 | 4 (personsd(xingxing 0)animal)
偏移量是4 4 4=8 所以会找到同一个数据,只有一份 */
代码语言:javascript复制void test04()
{
persons p;
p.monkey::age = 100;//monkey::作用域下
p.xingxing::age = 200;//xingxing::作用域下
cout << p.monkey::age << endl;
cout << p.xingxing::age << endl;
cout << p.age << endl;
}
代码语言:javascript复制int main()
{
//testt();
//test01();
//test02();
//test03();
test04();
system("pause");
return 0;
}
当父类中有保护权限,私有权限时,会继承到子类中吗? 按道理来说,父类中所有非静态成员属性会被子类继承下去,所以父类中私有成员属性确实是被继承下来了,但是被编译器隐藏起来了。
可以利用开发命令提示工具查看对象·模型 (更清晰,明了) 首先先跳转到该位置的盘 比如 D:盘等 cd 到指定具体位置下的文件路径(看自己写的文件名) 输入 cl /d1 reportSingleClassLayout类名 文件名
最后说明一下: 继承中构造和析构的顺序是?: 先构造父类,再构造子类 先析构子类,再析构父类