文章目录
类的继承与派生的知识点
类的继承与派生:
- 继承与派生:保持已有类的特征构造新类的过程为继承,在已有类的基础上新增特性而产生新类的过程称为派生
- 继承目的:实现代码重用;派生目的:实现源程序的改造
- 声明:class 派生类:继承方式 基类
- 派生类:
吸收基类成员:派生类包含了基类中除了构造析构函数以外的所有成员,构造析构函数不会被继承
改造基类成员:虚函数重写(实际是虚函数表的覆盖)以及同名函数
添加新的成员:加入新的构造析构函数以及其他成员
类成员的访问:
public—>protected—>private注意基类中私有成员不能被访问
基类中的私有成员派生类无法访问
继承方式为public时权限不变,但是私有成员也会被继承?
继承方式为private何protected(体现类的继承特征)时,权限与继承方式一致
类型兼容规则:一个公有派生类的对象在使用上可以被当成基类的对象,反之不行
-
派生类的对象可以赋值给基类对象
-
派生类的对象可以初始化基类的引用
-
指向基类的指针可以指向派生类
通过基类的对象名与指针只能使用从基类继承的成员
#include<iostream>
#include <string>
using namespace std;
class Base
{
public:
void showBase()
{
cout << "base成员函数的调用" << endl;
}
};
class Son :public Base
{
public:
void showSon()
{
cout << "Son成员函数的调用" << endl;
}
};
int main()
{
Son s1;
Base b1 = s1;//派生类对象赋值给基类对象
Base& b2 = s1;//派生类对象初始化基类的引用
Base* b3 = &s1;//派生类地址初始化基类指针/基类指针指向派生类
b1.showBase();//通过基类的对象名和指针只能调用基类成员
b2.showBase();
b3->showBase();
return 0;
}
单继承与多继承
-
单继承:一个基类一个派生类
-
多继承:多基类一派生 class 派生类:继承方式1 基类1, 继承方式2 基类2
-
多重派生:一个基类多个派生类
-
多层派生:派生类为基类继续派生
派生类的构造与析构
-
基类的构造析构函数不会被继承,派生类需要写自己的构造析构函数
-
派生类的构造函数需要给基类构造函数传递参数,注意基类成员用基类名在初始化列表进行初始化!!!
#include<iostream>
#include <string>
using namespace std;
class Base
{
public:
int m_A;
Base(int a) :m_A(a) {}//如果有默认构造,派生类构造时可以不传参
void showBase()
{
cout << "m_A=" << m_A << endl;
}
};
class Son :public Base
{
public:
int m_B;
Son(int a, int b) :Base(a), m_B(b) {}//注意基类用基类名在初始化列表进行初始化,多个基类类推
void showSon()
{
cout << "m_B=" << m_B << endl;
}
};
int main()
{
Son s(10, 20);
s.showBase();
s.showSon();
return 0;
}
类成员的标识与访问
-
当派生类与基类成员同名时,优先调用派生类成员,基类同名成员被屏蔽(包括重载)
-
通过作用域来访问
#include<iostream>
#include <string>
using namespace std;
class Base
{
public:
int m_A;
Base(int a) :m_A(a) {}
void show()
{
cout << "基类m_A=" << m_A << endl;
}
void show(int a)
{
cout << "基类重载" << endl;
}
};
class Son :public Base
{
public:
int m_A;
Son(int a1, int a2) :Base(a1), m_A(a2) {}
void show()
{
cout << "派生类m_B=" << m_A << endl;
}
};
int main()
{
Son s(10, 20);
s.show();//默认派生类,屏蔽了基类同名成员,包括重载
s.Base::show();//作用域访问基类
s.Base::show(10);//作用域访问基类重载类型
return 0;
}
- 菱形继承引发的二义性问题:B1,B2继承A,C继承B1和B2,解决方法:同名屏蔽或虚函数
A类称为虚基类,在继承前加virtual,vbptr虚基类指针virtual base pointer指向虚基数表
#include <iostream>
using namespace std;
class BaseA
{
public:
int m_A;
BaseA(int a) :m_A(a) {}
};
class BaseB1 :virtual public BaseA//虚继承
{
public:
int m_B1;
BaseB1(int a, int b1) :BaseA(a), m_B1(b1) {}
};
class BaseB2 :virtual public BaseA//虚继承
{
public:
int m_B2;
BaseB2(int a, int b2) :BaseA(a), m_B2(b2) {}
};
class SonC :public BaseB1, public BaseB2
{
public:
int m_C;
SonC(int a, int b1, int b2, int c) :BaseA(a), BaseB1(a, b1), BaseB2(a, b2), m_C(c) {}
};
int main()
{
SonC c(30, 20, 20, 30);//B1,B2也可以初始化虚基类,但是C直接初始化优先级更高,调用了一次
cout << c.m_A << endl;
return 0;
}
建立对象所指定的类称为最(远)派生类
虚基类的成员由最派生类调用虚基类的构造函数进行初始化,在初始化列表调用构造函数初始化。
虚函数与纯虚函数在多态进行总结
类的继承与派生的实验结果
类型兼容规则
派生类的析构与构造
类成员的标识与访问
菱形继承
总结:通过这次试验,理解赋值兼容性原则,掌握派生类的复制构造函数的定义方法;在派生类中可以通过基类名调用基类的成员。又通过做实验加深对多重继承方式以及两个类派生出新类。在类体中声明成员函数,在类外定义成员函数等。掌握类的继承与派生的实现方法;定义合适的派生类构造函数,用于初始化基类成员和对象成员。继承是在一个已有的类上建立一个新的类,已存在的类称为基类,新建立类称为派生类。继承的方式有public,private和protected三种,默认为private.继承的方式限定了基类成员在派生类中的访问权限:类的public成员可以通过对象来访问,private成员不能通过对象和派生类访问,而protected也不能通过对象访问,但是基类protected成员可以在派生类中访问。