继承与派生
1.派生类的定义
1.定义:类的继承是新的类从已有类那里得到己有的特性,从已有类产生新类的过程就是类的派生。原有类称为基类或父类,产生的新类称为派生类或子类。
代码示例:
/* //定义语法 class 派生类名:继承方式1 基类1,继承方式2 基类2 { 派生类成员声明; }; */ class Did:public Did1,private Did2 { public: Did(); ~Did(); };
2.生成派生类
1)吸收基类成员
将基类成员全盘吸收 ,派生类包含了除构造和析构函数之外所有成员。(定义派生类后自动完成,无法干预)
2)改造基类成员
基类成员访问控制问题,依靠派生类定义时的继承方式来控制。
对基类数据或函数成员覆盖与隐藏。
同名隐藏:申明了一个与基类成员同名的新成员,派生类新成员隐藏了外层同名成员。
3)添加新的成员
3.继承种类
1)单继承:也就是一个子类只有一个父类。
class 派生类名:继承方式 基类名 { 派生类新定义成员 };
2)多继承:就是一个子类可以有多个父类。
class 派生类名:继承方式1 基类1,继承方式2 基类2 { 派生类成员声明; };
示例:
#include "pch.h" #include<iostream> using namespace std; class did { public: int var0; void fun0() { cout << "member of did" << endl; } }; class did1 : public did { public: int var1; }; class did2 : public did { public: int var2; }; class dided :public did1, public did2 { public: int var; void fun0() { cout << "member of dided of fun0" << endl; } void fun() { cout << "member of dided" << endl; } }; int main() { dided d; d.did1::var0 = 0; d.fun0(); d.fun(); d.did2::fun0();//调出隐藏函数 d.var1 = 2; cout << d.did1::var0 << endl; cout << d.var1 << endl; return 0; }
运行截图:
2.访问控制(三种继承方式):继承方式规定了如何访问从基类继承的成员
1.公有继承(public):公有继承的特点是基类的公有成员和保护成员作为派生类的成员时,它们都保持原有的状态,而基类的私有成员仍然是私有的。
示例:
#include "pch.h" #include <iostream> #include <stdlib.h> #include <string> using namespace std; class person { public: string m_strname; void eat() { cout << "eat" << endl; } }; class soldier :public person { public: string m_strcode; void attack() { cout << "attack()" << endl; } }; int main(void) { // 创建soldier对象 soldier soldier; //soldier.m_strname = "jim"; // 错误 保护继承不可用派生类对象直接访问基类成员 //soldier.eat(); // 错误 保护继承不可用派生类对象直接访问基类成员函数 soldier.m_strcode = "592"; cout << soldier.m_strcode << endl; // 调用对象方法 soldier.attack(); //soldier.m_strname = "Bob";// 错误 私有继承不可用派生类对象直接访问基类成员 //soldier.eat(); // 错误 私有继承不可用派生类对象直接访问基类成员函数 //soldier.person::eat(); soldier.m_strname = "jim"; cout << soldier.m_strname << endl; soldier.eat(); return 0; }
运行截图:
2.保护继承(protected):保护继承的特点是基类的所有公有成员和保护成员都成为派生类的保护成员,并且只能被它的派生类成员函数或友元访问,基类的私有成员仍然是私有的。
示例:
#include "pch.h" #include <iostream> #include <stdlib.h> #include <string> using namespace std; class person { public: string m_strname; void eat() { cout << "eat" << endl; } }; class soldier :protected person { public: string m_strcode; void attack() { void eat(); m_strname="Jim"; // 用派生类的成员函数调用保护继承来的成员 cout << "attack()" << endl; cout << m_strname << endl; } }; int main(void) { // 创建soldier对象 soldier soldier; //soldier.m_strname = "jim"; // 错误 保护继承不可用派生类对象直接访问基类成员 //soldier.eat(); // 错误 保护继承不可用派生类对象直接访问基类成员函数 soldier.m_strcode = "592"; cout << soldier.m_strcode << endl; // 调用对象方法 soldier.attack(); return 0; }
运行截图:
3.私有继承(private):私有继承的特点是基类的公有成员和保护成员都作为派生类的私有成员,并且不能被这个派生类的子类所访问。
注意:如果不给出继承方式关键字,系统默认为私有继承。
示例:
#include "pch.h" #include <iostream> #include <stdlib.h> #include <string> using namespace std; class person { public: string m_strname; void eat() { cout << "eat" << endl; } }; class soldier :private person { public: string m_strcode; void attack() { cout << "attack()" << endl; } }; int main(void) { // 创建soldier对象 soldier soldier; //soldier.m_strname = "jim"; // 错误 保护继承不可用派生类对象直接访问基类成员 //soldier.eat(); // 错误 保护继承不可用派生类对象直接访问基类成员函数 soldier.m_strcode = "592"; cout << soldier.m_strcode << endl; // 调用对象方法 soldier.attack(); //soldier.m_strname = "Bob";// 错误 私有继承不可用派生类对象直接访问基类成员 //soldier.eat(); // 错误 私有继承不可用派生类对象直接访问基类成员函数 //soldier.person::eat(); return 0; }
运行截图:
3.派生类的构造函数和析构函数
1.定义语法:如果对基类初始化时,需要调用基类的带有形参表的构造函数时,派生类就必须声明构造函数。(析构函数同理)
派生类名::派生类名(参数表):基类1(基类1初始化参数表),..., 基类n(基类n初始化参数表),成员对象名1(成员对象名1初始化参数表),..., , 成员对象名n(成员对象名n初始化参数表) { 派生类构造函数和其他初始化操作; };
2.例子:
#include "pch.h" #include <iostream> #include <stdlib.h> #include <string> using namespace std; class A { public: A(int i) { cout << "A" << i << endl; } }; class B { public: B(int j) { cout << "B" << j << endl; } }; class C { public: C() { cout << "C" << endl; } }; class De: public A , public B , public C { public: De(int a, int b, int c, int d) :A(a), B(d), m1(c), m2(b) {} private: A m1; B m2; C m3; }; int main() { De obj(1, 2, 3, 4); return 0; }
运行截图:
4.虚基类
1.定义:将共同基类设置为虚基类,这是从不同的路径继承过来的同名数据成员在成员函数内存中就只有一个副本,同时函数名也只有一个映射。
2.例子:
#include "pch.h" #include <iostream> #include <stdlib.h> #include <string> using namespace std; class A { public: int varA; void funA() { cout << "A" << endl; } }; class B :virtual public A { public: int varB; }; class C :virtual public A { public: int varC; }; class De : public B, public C { public: int varDe; void fun() { cout << "De" << endl; } }; int main() { De obj; obj.varA = 0; obj.funA(); return 0; }
运行截图: