欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

C++中的重載、覆蓋、隱藏介紹

 更新時(shí)間:2021年10月01日 22:54:43   投稿:mdxy-dxy  
這篇文章主要介紹了C++中的重載、覆蓋、隱藏介紹,需要的朋友可以參考下

前幾天面試時(shí)被問及C++中的覆蓋、隱藏,概念基本答不上來(lái),只答了怎么用指針實(shí)現(xiàn)多態(tài),也還有遺漏。最終不歡而散。回來(lái)后在網(wǎng)上查找學(xué)習(xí)了一番,做了這個(gè)總結(jié)。其中部分文字借用了別人的博客,望不要見怪。

概念

一、重載(overload)

指函數(shù)名相同,但是它的參數(shù)表列個(gè)數(shù)或順序,類型不同。但是不能靠返回類型來(lái)判斷。
(1)相同的范圍(在同一個(gè)作用域中) ;
(2)函數(shù)名字相同;
(3)參數(shù)不同;
(4)virtual 關(guān)鍵字可有可無(wú)。
(5)返回值可以不同;

二、重寫(也稱為覆蓋 override)

是指派生類重新定義基類的虛函數(shù),特征是:
(1)不在同一個(gè)作用域(分別位于派生類與基類) ;
(2)函數(shù)名字相同;
(3)參數(shù)相同;
(4)基類函數(shù)必須有 virtual 關(guān)鍵字,不能有 static 。
(5)返回值相同(或是協(xié)變),否則報(bào)錯(cuò);<—-協(xié)變這個(gè)概念我也是第一次才知道…

(6)重寫函數(shù)的訪問修飾符可以不同。盡管 virtual 是 private 的,派生類中重寫改寫為 public,protected 也是可以的

三、重定義(也成隱藏)

(1)不在同一個(gè)作用域(分別位于派生類與基類) ;
(2)函數(shù)名字相同;
(3)返回值可以不同;
(4)參數(shù)不同。此時(shí),不論有無(wú) virtual 關(guān)鍵字,基類的函數(shù)將被隱藏(注意別與重載以及覆蓋混淆) 。
(5)參數(shù)相同,但是基類函數(shù)沒有 virtual關(guān)鍵字。此時(shí),基類的函數(shù)被隱藏(注意別與覆蓋混淆) 。

例子

#include <iostream>
using namespace std;
class SParent
{
public:
  SParent( ){};
  SParent( const SParent &p )
  {
    cout << "parent copy construct" << endl;
  }
  int add( int a,int b )
  {
    cout << "parent int add" << endl;
    return a + b;
  }
  double add( double a,double b )
  {
    cout << "parent double add" << endl;
    return a + b;
  }
  virtual int dec( int a,int b )
  {
    cout << "parent int dec" << endl;
    return a - b;
  }
};
class SChild : public SParent
{
public:
  //using SParent::add;
  float add( float a,float b )
  {
    cout << "child float add" << endl;
    return a + b;
  }
  int dec(int a, int b)
  {
    cout << "child int dec" << endl;
    return a - b;
  }
};
int main()
{
  /* 測(cè)試重載 */
  SParent parent;
  parent.add( 3,5 );
  parent.add( (double)3,(double)5 );
  cout << endl;
  /* 測(cè)試覆蓋 */
  SChild *pchild = (SChild *)new SParent();/* 基類強(qiáng)轉(zhuǎn)為子類...危險(xiǎn)...,用dynamic_cast轉(zhuǎn)換也不行 */
  pchild->dec( 10,3 );
  SParent *pparent = new SChild();
  pparent->dec( 11,3 );
  cout << endl;
  /* 測(cè)試隱藏 */
  SChild child;
  child.add( (int)3,(int)5 );
  cout << endl;
  /* 測(cè)試函數(shù)表 */
  ((SParent *)NULL)->add( 4,6 );
  ((SChild *)NULL)->add( 4,6 );
  int a = 0;
  ((SChild *)&a)->add( 4,6 );
   cout << endl;
  /* 測(cè)試函數(shù)地址 */
  ((SParent)child).add( (int)4,(int)8 );
  child.SParent::add( 3,5 );

  return 0;
}

輸出結(jié)果:

parent int add
parent double add

parent int dec
child int dec

child float add

parent int add
child float add
child float add

parent copy construct
parent int add
parent int add
按 <RETURN> 來(lái)關(guān)閉窗口...

理解

int SParent::add(int a,int b)與double SParent::add( double a,double b )是重載

int SParent::add(int a,int b)與double SParent::add( double a,double b )都被子類SChild中的float SChild::add( float a,float b )隱藏

int SParent::dec( int a,int b )被子類SChild中的int SChild::dec( int a,int b )覆蓋

測(cè)試

1.重載測(cè)試,簡(jiǎn)單易懂,略過。

2.覆蓋測(cè)試。dec函數(shù)在基類、子類中同名同參,為虛函數(shù),故稱覆蓋。

SChild *pchild = (SChild *)new SParent()創(chuàng)建的是一個(gè)基類對(duì)象,其函數(shù)表應(yīng)該為

SParent *pparent = new SChild();創(chuàng)建一個(gè)子類對(duì)象,其函數(shù)表應(yīng)該為

由上面的函數(shù)表可見,當(dāng)發(fā)生覆蓋時(shí),子類的函數(shù)名會(huì)把基類的同名函數(shù)覆蓋(這也就是為什么叫覆蓋的原因吧)。這樣我們可以利用一個(gè)指向子類的基類指針實(shí)現(xiàn)多態(tài)。但重點(diǎn)只有一
個(gè),就是函數(shù)表里到底指向誰(shuí)(不管這個(gè)指針經(jīng)過轉(zhuǎn)換后是什么類型的).故輸出分別為父類、子類。這是一個(gè)運(yùn)行時(shí)多態(tài)。

3.隱藏測(cè)試

int SParent::add(int a,int b)與double SParent::add( double a,double b )都被子類SChild中的float SChild::add( float a,float b )覆蓋,是因?yàn)樗麄兺以诓煌淖饔糜蛑?基類、子類作用域是不同的)。child.add( (int)3,(int)5 );這行代碼中,編譯器在子類中查找add函數(shù),只找到了一個(gè)(基類的add(int a,int b)會(huì)被編譯根據(jù)隱藏規(guī)則略過),再根據(jù)隱式類型轉(zhuǎn)換發(fā)現(xiàn)該函數(shù)適用。如果無(wú)法隱式轉(zhuǎn)換,則編譯不過。隱藏的原因:防止隱式類型轉(zhuǎn)換造成錯(cuò)誤。比如int也是可以轉(zhuǎn)換成char的,假如基類有一函數(shù)add(char a,char b),子類也有一函數(shù)add(double a,double b)。程序員想著在子類隱式把int轉(zhuǎn)換為double,但編譯器可能調(diào)的是基類的。這也防止了一些庫(kù)或封裝好的基類對(duì)程序員造成困擾。

  像上面的代碼,如果你確實(shí)需要基類的函數(shù),可以用using SParent:add。則把基類的add函數(shù)域擴(kuò)大到了子類,構(gòu)成重載。

4.函數(shù)表測(cè)試

上面我們說到函數(shù)表,這個(gè)是在編譯時(shí)定好的,程序運(yùn)行時(shí)加載到內(nèi)存中。這意味著我們可以直接通過地址去調(diào)用函數(shù)。所以((SChild *)NULL)->add( 4,6 );這種代碼也是能運(yùn)行通過的。網(wǎng)上還有人通過計(jì)算直接取到了函數(shù)表的地址直接調(diào)用了。但這種代碼不安全不規(guī)范不說,還有個(gè)更大的問題。當(dāng)成員函數(shù)里需要調(diào)用成員變量時(shí),通過這種假的對(duì)象指針肯定找不到成員變量表,直接訪問了非法內(nèi)存。

5.函數(shù)地址測(cè)試

有了隱藏、覆蓋,哪么我們要怎么調(diào)用被隱藏、覆蓋的函數(shù)呢。下面有兩種方法:

    ((SParent)child).add( (int)4,(int)8 );
    child.SParent::add( 3,5 );

第一種是比較低效的方法。事實(shí)上它是通過拷貝構(gòu)造函數(shù)生成一個(gè)臨時(shí)的基類變量去調(diào)用基類的add函數(shù)。
第二種通過::指定域去訪問。這種方法是編譯器根據(jù)域直接找到了基類的函數(shù)地址,跟函數(shù)表沒有多大關(guān)系。

相關(guān)文章

  • c++連接mysql5.6的出錯(cuò)問題總結(jié)

    c++連接mysql5.6的出錯(cuò)問題總結(jié)

    下面小編就為大家?guī)?lái)一篇c++連接mysql5.6的出錯(cuò)問題總結(jié)。小編覺得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過來(lái)看看吧,祝大家游戲愉快哦
    2016-12-12
  • QT獲取顯示當(dāng)前時(shí)間和日期的方法(用QTime,QDate和QDateTime)

    QT獲取顯示當(dāng)前時(shí)間和日期的方法(用QTime,QDate和QDateTime)

    獲取當(dāng)期日期時(shí)間在我們?nèi)粘i_發(fā)中經(jīng)常會(huì)遇到,下面這篇文章主要給大家介紹了關(guān)于QT獲取顯示當(dāng)前時(shí)間和日期的相關(guān)資料,文中通過實(shí)例代碼介紹的非常詳細(xì),需要的朋友可以參考下
    2022-08-08
  • C++編程中的格式化輸出詳解

    C++編程中的格式化輸出詳解

    這篇文章主要介紹了C++編程中的格式化輸出詳解,是C++入門學(xué)習(xí)中的基礎(chǔ)知識(shí),需要的朋友可以參考下
    2015-09-09
  • C語(yǔ)言實(shí)現(xiàn)四窗口聊天

    C語(yǔ)言實(shí)現(xiàn)四窗口聊天

    這篇文章主要為大家詳細(xì)介紹了C語(yǔ)言實(shí)現(xiàn)四窗口聊天,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2021-06-06
  • C++實(shí)現(xiàn)簡(jiǎn)單學(xué)生信息管理系統(tǒng)

    C++實(shí)現(xiàn)簡(jiǎn)單學(xué)生信息管理系統(tǒng)

    這篇文章主要為大家詳細(xì)介紹了C++實(shí)現(xiàn)簡(jiǎn)單學(xué)生信息管理系統(tǒng),文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2022-03-03
  • c++中的4種類型轉(zhuǎn)化方式詳細(xì)解析

    c++中的4種類型轉(zhuǎn)化方式詳細(xì)解析

    const_cast該函數(shù)用于去除指針變量的常量屬性,將它轉(zhuǎn)換為一個(gè)對(duì)應(yīng)指針類型的普通變量。反過來(lái),也可以將一個(gè)非常量的指針變量轉(zhuǎn)換為一個(gè)常指針變量
    2013-10-10
  • C語(yǔ)言順序查找算法介紹及示例

    C語(yǔ)言順序查找算法介紹及示例

    順序查找又稱線性查找,主要用于在線性表中進(jìn)行查找。順序查找通常分為對(duì)一般的無(wú)序線性表的順序查找和對(duì)按關(guān)鍵字有序的順序表的順序查找,下面我們來(lái)一探究竟
    2022-08-08
  • C++堆排序算法實(shí)例詳解

    C++堆排序算法實(shí)例詳解

    這篇文章主要介紹了C++堆排序算法,簡(jiǎn)單分析了堆排序算法的原理并結(jié)合實(shí)例形式分析了C++實(shí)現(xiàn)堆排序的具體操作技巧,需要的朋友可以參考下
    2017-08-08
  • 深入淺出理解C語(yǔ)言初識(shí)結(jié)構(gòu)體

    深入淺出理解C語(yǔ)言初識(shí)結(jié)構(gòu)體

    C?數(shù)組允許定義可存儲(chǔ)相同類型數(shù)據(jù)項(xiàng)的變量,結(jié)構(gòu)是?C?編程中另一種用戶自定義的可用的數(shù)據(jù)類型,它允許你存儲(chǔ)不同類型的數(shù)據(jù)項(xiàng),本篇讓我們來(lái)了解C?的結(jié)構(gòu)體
    2022-02-02
  • C++中求組合數(shù)的各種方法總結(jié)詳解

    C++中求組合數(shù)的各種方法總結(jié)詳解

    本篇文章是對(duì)C++中的求組合數(shù)的各種方法進(jìn)行了詳細(xì)的介紹。需要的朋友參考下
    2013-05-05

最新評(píng)論