继承与多继承
概念:
生活中:
子继承父遗留给的物质或精神产业
代码中继承:
子类 继承 父类 , 可以降低代码的 冗余度 提高代码的复用率
名词:
子类继承父类
父类派生子类
注意:
一个父类可以派生多个子类
多个子类可以继承一个父类
一个类可以继承多个父类
继承的方式
作用: 约束子类使用父类成员的范围
private 将父类中所以成员变为private修饰
protected 父类中私有的还是私有的 ,受保护的还是受保护的 公共的变为受保护的
public 父类成员访问是什么 在子类中就是什么(推荐使用)
子类不能继承父类的构造函数但是可以调用 因为 构造函数时创建对象 也就是子类不能创建父类对象
所以 创建对象的时候 子类自己创建构造函数去创建
继承的语法
语法:
class 子类名:继承方式 父类名,继承方式 父类名2,....
{
//编写子类成员
};
子类调用父类构造函数
子类名(形参列表):父类名(形参1 ,形参2 ,....)
//就是调用父类构造函数
// 有参 就是调用父类的有参构造
子父类对象转换
1 子类对象转换为父类对象
自动转换
无风险
如:
Dod d1;
Anim &a =d;
2 父类对象转换为子类对象
有风险 少用
强制转换
如:
Cat C;
Anim &a=c;
Dog& d =(Dog&)a;(有风险)
Cat& c2 =(Cat&)a;
注意: 在强制转换时有风险,需要自身判断否可以转换
强制转换可以转成功 语法没问题 但是会有脏数据 所以 就不是本能控制的
继承关系中同名成员的区分【一般不出现】
怎么区分 ?
子类对象.成员变量名 子类成员变量
子类对象.父类名::成员变量名 父类成员变量
子父类中函数名同名 也一样
子类对象.成员函数名(实参列表)
子类对象.父类名::成员函数名(实参列表)
不可继承的
子类继承父类的所有属性和函数 但是 不继承构造函数析构函数
构造函数 都是创建对象的
析构函数 销毁对象的
所以 子类不能 继承
父类构造函数
父类拷贝构造
父类析构
operator =
私有的可以继承 不能直接访问
继承中的构造与析构顺序
和现实一样 肯定先有父后才会有子 代码中 先子析构 父后析构
父子类中
父构
子构
子析
父析
父子孙类中
父构
子构
孙构
孙析
子析
父析
子类成员变量为其他类的对象
父类构造
成员构造
子类构造
子类析构
成员析构
父类析构
多继承
概念: 一个子类有多个父类
#include <iostream> using namespace std; class Ma { public: char name[50]; }; class Lv { public: char name[50]; }; class LuoZi : public Ma, public Lv { public: char name[50]; }; int main(int argc, char const *argv[]) { LuoZi lz; lz.Ma::name; lz.Lv::name; lz.name; return 0; }
菱形继承(了解)
概述:
A派生B,C,D多继承B,C,此时菱形继承 此时D中将有两份A的成员
示例
#include <iostream> using namespace std; class Anim { public: char name[50]; }; class Ma : public Anim { }; class Lv : public Anim { }; class LuoZi : public Ma, public Lv { }; int main(int argc, char const *argv[]) { LuoZi lz; lz.Ma::name; lz.Lv::name; return 0; }
虚继承
作用:
解决 多继承或菱形继承得到的多份
语法
: 当类继承时在继承方式前加 virtual
注意
: A派生B,C,D继承B,C,给B,C继承A时加
示例
#include <iostream>
#include <string.h>
using namespace std;
class Anim
{
public:
char name[50];
};
class Ma : virtual public Anim
{
};
class Lv : virtual public Anim
{
};
class LuoZi : public Ma, public Lv
{
};
int main(int argc, char const *argv[])
{
LuoZi lz;
strcpy(lz.Ma::name, "骡子(马)");
strcpy(lz.Lv::name, "骡子(驴)");
strcpy(lz.name, "骡子");
cout << lz.Ma::name << endl;
cout << lz.Lv::name << endl;
cout << lz.name << endl;
return 0;
}
类图
虚继承前的类图
Anim
Ma
Lv
LuoZi
有 虚继承的类图
Anim
Ma
Lv
LuoZi