栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > C/C++/C#

【C++继承与派生】

C/C++/C# 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

【C++继承与派生】

继承与派生 (一)类的三种访问(控制)方式
  • private(class默认访问方式):仅定义该成员的类内部可以访问
  • protected:派生类可以访问,类外部不可以访问
  • public(struct默认访问方式):均可访问
(二)派生类的继承方式与访问控制:

派生类可以通过访问方式对基类成员的访问方式进行改造:

1)private(私有继承):

只有定义该成员的类内部可以访问,不允许派生类访问(不论是什么继承方式)。

2)protected(保护继承):

基类除了private成员,在派生类中的访问方式均为protected。

3)public(公有继承):

基类除了private成员,在派生类中的访问控制与基类一致。

(三)派生类生成的过程: 1)吸收基类成员

派生类会除了基类的构造函数、析构函数以外的所有数据成员和函数成员。

2)改造基类成员

通过访问方式,数据和函数成员的覆盖对基类成员进行改造。

3)添加新成员

尤其是添加构造函数和析构函数

(四)派生类的构造和析构函数
  1. 派生类没有继承基类的构造和析构函数
  2. 派生类必须对新增的成员初始化,还需要初始化基类的成员
1)派生类的构造函数定义格式:

派生类名(参数表):需要初始化的基类名(参数表),新增成员初始化列表 { 构造函数体 }

【PS】:若没有在派生类构造函数中显示初始化基类,则默认调用基类的无参构造函数(此时需基类有无参构造函数)

2)派生类构造函数的执行顺序:

1、调用基类的构造函数(按继承时说明从左到右的顺序,与初始化列表无关)
2、(如果有的话)调用子对象的构造函数(按类中说明的顺序)
3、执行派生类构造函数的函数体

执行析构函数的顺序与此正好相反

代码示例:

#include 
using namespace std;

class Base {
private:
    int bi; //私有成员
public:
    Base() {
        bi=0;
        cout<<"执行基类Base的构造函数n";
    }
    ~Base() {
        cout<<"执行基类Base["< 
(五)派生类的拷贝构造函数 
//派生类的拷贝构造函数的一般格式如下:
Derived(const Derived &d):Base(d)
{
  //用派生类的引用去初始化基类的引用合法!  //正常的派生类的拷贝构造函数体
}//Base:基类,Derived:派生类

(六)基类和派生类指针
  1. 派生类的成员函数将覆盖基类的所有同名成员函数(含重载的同名函数)。

    【注意1】:覆盖不是重载,可以通过**Base::show()**来限定。

    【注意2】:若是通过基类指针指向派生类,调用同名函数,则执行的基类的函数。(基类指针不知道派生类新增成员的存在)。

    • 这也引出了一个问题——【为什么要有虚函数?】:

      ​ 正是由于【注意点2】所说,基类指针只能调用基类成员函数,而不能调用派生类中的新增成员函数,如果使用虚函数,就能够实现用基类指针访问派生类的成员函数,基于这一点,派生类中的这个成员函数和基类的虚函数的形式要完全相同,并且在派生类中实现重写(一个接口多种方法)。

  2. 不能通过基类的对象(或指针)访问派生类新增的(共有)成员。

    【例1】:

    #include 
    using namespace std;
    
    class Base
    {
    	public:
    		void print(int a=0)
    		{
    			cout<<"Print in Base"<print();	//执行基类的print,基类指针并不知道派生类中的新增函数 
    	//bp->showDerived();	 报错,理由同上、
    	
    } 
    
    //输出结果如下:
     
    

  3. 派生类指针不能直接指向基类对象(编译报错),否则可能会使用派生类中的新增成员(在基类中是未定义的),即使是强制转化成基类指针也是调用派生类的函数。

    总之,派生类指针无法访问基类成员。

  4. 基类指针指向派生类是安全的,但是只能用来调用基类的成员。

    若要访问派生类的新增成员,需要进行强制转化。

    ((Derived *)bp)->print();	
    //调用的是派生的print(强制转化后,相当于是一个派生类指针,可以访问派生类成员函数)
    //外面的括号不能省略!!(优先级问题!!)
    
    

【例2】派生类和基类指针的相互转化

//派生类和基类指针的相互转化
#include 
using namespace std;

class Base
{
	public:
		void print()
		{
			cout<<"Print in Base"<print(); 		 
	
	//派生类指针指向基类---报错 
//	dp=&bObj; 	
    //将基类地址赋给派生类需要进行强制转化!!	
	dp=(Derived *)&bObj;
  	dp->print(); 
  	dp->show();
} 


(七)虚基类 1)概念与声明方式

虚基类(在访问方式前加virtual)

在多层次继承中,若直接基类派生自同一个间接基类,会有两份的间接基类成员。

在虚基类机制下,虽然被一个派生类间接地多次继承,但派生类只继承一份该基类的成员。

2)虚基类下构造函数的执行顺序:

1、直接基类中的虚基类的构造函数在非虚基类之前调用
2、多个虚基类按继承时说明从左到右的顺序执行
3、若虚基类由非虚基类派生而来,则仍先调用基类构造函数,再按派生类中的构造函数的执行顺序调用
4、执行派生类构造函数的函数体

执行析构函数的顺序与此正好相反

3)初始化派生类
  • 对于非虚基类,在派生类的构造函数中初始化间接基类是不允许的;
  • 而对于虚基类,则必须在派生类中对虚基类初始化。

例如person是teacher和student的虚基类,则在派生类assistant的构造函数一定要初始化虚基类。

若person不是teacher和student的虚基类,则不允许派生类assistant初始化间接基类person。

注意:虚基类并不是在声明基类时声明的,而是在声明派生类是,指定继承方式时声明的。因为一个基类可以在生成一个派生类作为虚基类,而在生成另一个派生类时不作为虚基类。

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/989739.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号