一 .基本概念(类之间的关系)
继承就是在已有类的基础上创建新类的过程 已有的类叫做基类或父类,新类则叫做派生类或子类
二.基类和派生类
(一)类继承关系的语法形式
class 派生类名: 基类名表
{
数据成员和成员函数声明
};
基类名表的构成
访问控制 基类名1, 访问控制 基类名2,… ,访问控制 基类名n
访问控制表示派生类对基类的继承方式:
public 公有继承
private 私有继承
protected 保护继承
(二)访问控制
派生类不能直接使用基类的私有成员
(三)派生类的生成过程
1.吸收基类成员(全部吸收(构造、析构除外),但不一定可见)
在C++的继承机制中,派生类吸收基类中除构造函数和析构函数之外的全部成员。
2.改造基类成员
通过在派生类中定义同名成员(包括成员函数和数据成员)来屏蔽(隐藏)在派生类中不起作用的部分基类成员。
3.添加派生类新成员
仅仅继承基类的成员是不够的,需要在派生类中添加新成员,以保证派生类自身特殊属性和行为的实现。
(四)class Father
{
int a,b;
public:
// 成员函数
};
class Son:public Father
{
int c;
public:
// 成员函数
};
(1)公有继承:
基类 派生类
private成员
protected成员 protected成员
public成员 public成员
private成员
protected成员
public成员
以公有方式继承的派生类,基类的public和protected成员在派生类中性质不变,派生类可以直接使用这些成员。
定义一个基类person(不定义构造函数)
姓名、性别、年龄(访问权限设置为私有)
定义公有的成员函数set_p()
定义公有的成员函数display_p(),显示person的信息
再由基类派生出学生类(不定义构造函数,采用公有继承的方式)
增加学号、班级、专业和入学成绩
定义公有成员函数set_t()
定义成员函定义公有的成员函数display_s(),显示所有的信息
#include<iostream>
#include <string>
using namespace std;
class Person
{
string name;
int age;
string sex;
public:
void set_p() {
cout<<"name\tage\tsex"<<endl;
cin>>name>>age>>sex;
}
void show_p() {
cout<<name<<" "<<age<<" "<<sex<<endl;
}
};
class student :public Person
{
string no;
string zhuanye;
string t_class;
float score;
public:
void set_t(){
set_p(); //调用继承于基类的成员函数访问继承于基类的私有数据成员
cout<<"zhuanye\tt_class\tscore"<<endl;
cin>>zhuanye>>t_class>>score;
}
void show_t() {
show_p();
cout<<zhuanye<<" "<<t_class<<" "<<score<<endl;
}
};
二.派生类对象结构
派生类定义了与基类同名的成员,在派生类中访问同名成员时屏蔽(hide)了基类的同名成员
在派生类中使用基类的同名成员,显式地使用类名限定符:
类名 :: 成员
四. 派生类中访问静态成员
基类定义的静态成员,将被所有派生类共享(基类和派生类共享基类中的静态成员)
根据静态成员自身的访问特性和派生类的继承方式,在类层次体系中具有不同的访问性质
派生类中访问静态成员,用以下形式显式说明:
类名 :: 成员
或通过对象访问 对象名 . 成员
基类定义的静态成员,将被所有派生类共享(基类和派生类共享基类中的静态成员)。派生类中访问静态成员,用以下形式显式说明:类名:: 成员或通过对象访问 对象名 . 成员
五.基类的初始化
在创建派生类对象时用指定参数调用基类的构造函数来初始化派生类继承基类的数据。
派生类构造函数声明为:
派生类构造函数 ( 变元表 ) : 基类 ( 变元表 ) , 对象成员1( 变元表 )… 对象成员n ( 变元表 ) ;
构造函数执行顺序:基类 ? 对象成员 派生类
六.派生类构造函数和析构函数的定义规则
派生类构造函数和析构函数的使用原则
(1)基类的构造函数和析构函数不能被继承;
(2)如果基类没有定义构造函数或有无参的构造函数,派生类也可以不用定义构造函数;
(3)如果基类无无参的构造函数,派生类必须定义构造函数;
(4)如果派生类的基类也是派生类,则每个派生类只负责直接基类的构造;
(5)派生类是否定义析构函数与所属的基类无关
七.派生类构造函数的定义:在C++中,派生类构造函数的一般格式为:
派生类::派生类名(参数总表):基类名(参数表)
{
// 派生类新增成员的初始化语句
}
注意:这是基类有构造函数且含有参数时使用
八.派生类析构函数
1.当派生类中不含对象成员时
(1)在创建派生类对象时,构造函数的执行顺序是:基类的构造函数→派生类的构造函数;
(2)在撤消派生类对象时,析构函数的执行顺序是:派生类的析构函数→基类的析构函数。
2.当派生类中含有对象成员时
(1)在定义派生类对象时,构造函数的执行顺序:基类的构造函数→对象成员的构造函数→派生类的构造函数;
(2) 在撤消派生类对象时,析构函数的执行顺序:派生类的析构函数→对象成员的析构函数→基类的析构函数。
九.多继承
一个类有多个直接基类的继承关系称为多继承
1. 多继承声明语法
class 派生类名 : 访问控制 基类名1 , 访问控制 基类名2 , … , 访问控制 基类名n
{
数据成员和成员函数声明
};
2.类 C 可以根据访问控制同时继承类 A 和类 B 的成员,并添加自己的成员
classA
classB
class C:public A,public B
3.多继承的派生类构造和访问
(1)多个基类的派生类构造函数可以用初始式调用基类构造函数初始化数据成员。
(2)执行顺序与单继承构造函数情况类似。多个直接基类构造函数执行顺序取决于定义派生类时指定的各个继承基类的顺序。
(3) 一个派生类对象拥有多个直接或间接基类的成员。不同名成员访问不会出现二义性。如果不同的基类有同名成员,派生类对象访问时应该加以识别。
4.多继承的构造函数
派生类名(参数总表):基类名1(参数表1),基类名2(参数表2),…,基类名n(参数表n)
{
// 派生类新增成员的初始化语句
}
多继承方式下构造函数的执行顺序:
(1)先执行所有基类的构造函数
(2)再执行对象成员的构造函数
(3)最后执行派生类的构造函数
处于同一层次的各基类构造函数的执行顺序取决于定义派生类时所指定的基类顺序
与派生类构造函数中所定义的成员初始化列表顺序没有关系。
内嵌对象成员的构造函数执行顺序与对象在派生类中声明的顺序一致
心得:
在类的继承中,派生类继承基类的构造函数和析构函数之外的所有成员,但是不论哪种方式继承基类都不可以对基类的私有数据成员进行直接操作,但是可以通过基类中的成员函数来对基类中私有数据成员进行操作。
如果基类没有定义构造函数或有无参的构造函数,派生类也可以不用定义构造函数。
如果基类无无参的构造函数,派生类必须定义构造函数。
如果派生类的基类也是派生类,则每个派生类只负责直接基类的构造。派生类是否定义析构函数与所属的基类无关。可以再派生类中定义同名成员来隐藏派生类中部分不起作用的基类成员。
合理运用继承能够有效减少代码的复杂程度,提高写代码的效率,在可以考虑优化代码时使用等。