C++继承

        

1.继承概述

        面向对象程序设计中最重要的一个概念是继承。继承允许我们依据另一个类来定义另一个类,这使得创建和维护一个应用程序变得更容易。这样做,也达到了重用代码功能和提高执行时间的效果。

        当创建一个类时,不需要重新编写新的数据成员和成员函数,只需指定新建的类继承了一个已有的类的成员即可。这个已有的类称为基类,新建的类称为派生类

2.访问控制和继承

派生类可以访问基类中所有的非私有成员。因此基类成员如果不想被派生类的成员函数访问,则应在基类中声明为 private。我们可以根据访问权限总结出不同的访问类型,如下所示:

访问 public protected private
同一个类 yes yes yes
派生类 yes yes no
外部的类 yes no no

一个派生类继承了所有的基类方法,但下列情况除外:

  • 基类的构造函数、析构函数和拷贝构造函数。
  • 基类的重载运算符。
  • 基类的友元函数。

注:如果想访问基类的private成员,可以调用基类的Get函数访问。

3.重名成员和成员函数

如果在派生类中定义了与基类相同名称的成员或者函数,则基类的成员或者函数会被覆盖,但是可以显式调用,例如:

class  base
  { public :
           int  a ,  b ;  
  } ;
class  derived : public  base
  { public :  
         int  b ,  c ; 
  } ;
void  f ()
{ derived  d ;
   d . a = 1 ;
   d . base :: b = 2 ;//显式调用基类的成员
   d . b = 3 ;
   d . c = 4 ;
};
#include<iostream>
using namespace std ;
class A
{ public:	  
       int a1, a2 ;
      A( int i1=0, int i2=0 ) { a1 = i1; a2 = i2; }
      void print() 
         { cout << "a1=" << a1 << '\t' << "a2=" << a2 << endl ; }
};
class B : public A
{ public:	
       int b1, b2 ;
       B( int j1=1, int j2=1 ) { b1 = j1; b2 = j2; }
       void print()		//定义与同名函数
         { cout << "b1=" << b1 << '\t' << "b2=" << b2 << endl ; }
void printAB()
        { A::print() ; //派生类对象调用基类版本同名成员函数
           print() ; //派生类对象调用自身的成员函数
        }
};
int main()
{   B  b ;        
    b.A::print(); 
    b.printAB();  
}

//在C++中,派生类构造函数的一般格式为:
      //派生类::派生类名(参数总表):基类名(参数表)
     {
             // 派生类新增成员的初始化语句
     }
     //注意:这是基类有构造函数且含有参数时使用

4.构造函数和析构函数的执行顺序:

(1)当派生类中不含对象成员时

●在创建派生类对象时,构造函数的执行顺序是:基类的构造函数→派生类的构造函数;

●在撤消派生类对象时,析构函数的执行顺序是:派生类的析构函数→基类的析构函数。

(2)当派生类中含有对象成员时

●在定义派生类对象时,构造函数的执行顺序:基类的构造函数→对象成员的构造函数→派生类的构造函数;

●在撤消派生类对象时,析构函数的执行顺序:派生类的析构函数→对象成员的析构函数→基类的析构函数。

5.赋值兼容规则 
①.赋值兼容规则指在程序中需要使用基类对象的任何地方,都可以用公有派生类的对象来替代。

赋值兼容规则中所指的替代包括以下的情况:
  a 派生类的对象可以赋给基类对象
  b 派生类的对象可以初始化基类的引用
  c 派生类的对象的地址可以赋给基类类型的指针

②.通过公有继承:
派生类得到了除了构造、析构函数以外的所有成员
且这些成员的访问控制属性也和基类完全相同。
这样,它便具备了基类的所有功能。
利用赋值兼容规则:
a 派生类的对象可以赋给基类对象(强制类型转换)
b 派生类的对象可以初始化基类的引用
c 派生类的对象的地址可以赋给基类类型的指针
一个派生类对象也是一个基类对象,一个基类对象可派上用场的地方,派生类对象一样可派上用场。反之则不然。
6.继承学习心得
       在学习了继承之后,我觉得可以减少大量的代码,如果两个类之间有共性,或者说是需要限制基类的功能,而丰富派生类的功能,则可以使用继承。例如在设计管理系统的时候,基类只有查询功能,而派生类可以增加修改删除功能,这样就减少了不必要的代码开支,让程序更简洁。
全部评论

相关推荐

自从我室友在计算机导论课上听说了“刷&nbsp;LeetCode&nbsp;是进入大厂的敲门砖”,整个人就跟走火入魔了一样。他在宿舍门口贴了一张A4纸,上面写着:“正在&nbsp;DP,请勿打扰,否则&nbsp;Time&nbsp;Limit&nbsp;Exceeded。”日记本的扉页被他用黑色水笔加粗描了三遍:“Talk&nbsp;is&nbsp;cheap.&nbsp;Show&nbsp;me&nbsp;the&nbsp;code。”连宿舍聚餐,他都要给我们讲解:“今天的座位安排可以用回溯算法解决,但为了避免栈溢出,我建议用动态规划。来,这是状态转移方程:dp[i][j]&nbsp;代表第&nbsp;i&nbsp;个人坐在第&nbsp;j&nbsp;个位置的最优解。”我让他去楼下取个快递,他不直接去,非要在门口踱步,嘴里念念有词:“这是一个图的遍历问题。从宿舍楼(root)到驿站(target&nbsp;node),我应该用&nbsp;BFS&nbsp;还是&nbsp;DFS?嗯,求最短路径,还是广度优先好。”和同学约好出去开黑,他会提前发消息:“集合点&nbsp;(x,&nbsp;y),我们俩的路径有&nbsp;k&nbsp;个交点,为了最小化时间复杂度,应该在&nbsp;(x/2,&nbsp;y/2)&nbsp;处汇合。”有一次另一个室友低血糖犯了,让他帮忙找颗糖,他居然冷静地分析道:“别急,这是一个查找问题。零食箱是无序数组,暴力查找是&nbsp;O(n)。如果按甜度排序,我就可以用二分查找,时间复杂度降到&nbsp;O(log&nbsp;n)。”他做卫生也要讲究算法效率:“拖地是典型的岛屿问题,要先把连通的污渍区块都清理掉。倒垃圾可以用双指针法,一个指针从左往右,一个从右往左,能最快匹配垃圾分类。”现在我们宿舍的画风已经完全变了,大家不聊游戏和妹子,对话都是这样的:“你&nbsp;Two&nbsp;Sum&nbsp;刷了几遍了?”“别提了,昨天遇到一道&nbsp;Hard&nbsp;题,我连暴力解都想不出来,最后只能看题解。你呢?”“我动态规划还不行,总是找不到最优子结构。今天那道接雨水给我整麻了。”……LeetCode&nbsp;真的害了我室友!!!
老六f:编程嘉豪来了
AI时代还有必要刷lee...
点赞 评论 收藏
分享
评论
点赞
收藏
分享

创作者周榜

更多
牛客网
牛客网在线编程
牛客网题解
牛客企业服务