最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

C++中重載、重寫與隱藏從語法到底層實(shí)現(xiàn)

 更新時(shí)間:2026年07月09日 09:04:46   作者:小徐不徐說  
本文將從語法規(guī)則到底層實(shí)現(xiàn),全面解析三者的差異,并深入探討虛函數(shù)表(vtable)的工作原理,讓你徹底掌握面試常問問題,感興趣的可以了解一下

在 C++ 面向?qū)ο缶幊讨校?ldquo;重載(Overload)”、“重寫(Override)” 和 “隱藏(Hide)” 是三個(gè)極易混淆的概念。它們雖都涉及函數(shù)名的復(fù)用,但其語義、作用機(jī)制和使用場景卻截然不同。本文將從語法規(guī)則到底層實(shí)現(xiàn),全面解析三者的差異,并深入探討虛函數(shù)表(vtable)的工作原理。

一、函數(shù)重載(Overload)

? 定義

同一個(gè)作用域中,允許存在多個(gè)同名函數(shù),只要它們的參數(shù)簽名(參數(shù)個(gè)數(shù)、類型或順序)不同。編譯器會(huì)根據(jù)調(diào)用時(shí)的參數(shù)類型自動(dòng)匹配最合適的函數(shù)版本。

?? 核心特性

  • 作用域:同一類或同一命名空間內(nèi)
  • 區(qū)分依據(jù):參數(shù)列表(個(gè)數(shù)、類型、順序)必須不同(返回值類型不同不足以構(gòu)成重載)
  • 綁定方式:編譯期靜態(tài)綁定(編譯器在編譯時(shí)確定調(diào)用哪個(gè)函數(shù))
  • 與繼承無關(guān):僅針對(duì)同一作用域內(nèi)的函數(shù)

示例代碼

#include <iostream>
using namespace std;
class Calculator {
public:
    // 重載:參數(shù)類型不同
    int add(int a, int b) { return a + b; }
    double add(double a, double b) { return a + b; }
    // 重載:參數(shù)個(gè)數(shù)不同
    int add(int a, int b, int c) { return a + b + c; }
};
int main() {
    Calculator calc;
    cout << calc.add(2, 3) << endl;       // 調(diào)用 add(int, int)
    cout << calc.add(2.5, 3.5) << endl;   // 調(diào)用 add(double, double)
    cout << calc.add(1, 2, 3) << endl;    // 調(diào)用 add(int, int, int)
    return 0;
}

總結(jié)

重載的本質(zhì)是 “同名函數(shù)的多版本實(shí)現(xiàn)”,目的是讓函數(shù)名更直觀(如用 add 統(tǒng)一表示加法操作,無論參數(shù)是整數(shù)還是小數(shù)),其匹配邏輯由編譯器在編譯期完成。

二、函數(shù)重寫(Override)

? 定義

派生類中重新實(shí)現(xiàn)基類中聲明為 virtual 的函數(shù),要求函數(shù)簽名(函數(shù)名、參數(shù)列表、返回值類型)完全一致。重寫是實(shí)現(xiàn)多態(tài)的核心機(jī)制。

?? 核心特性

  • 作用域:派生類重寫基類的虛函數(shù)
  • 前提條件:基類函數(shù)必須用 virtual 聲明,派生類函數(shù)可加 override 關(guān)鍵字(C++11 起,用于顯式表明重寫意圖,編譯器會(huì)檢查匹配性)
  • 綁定方式:運(yùn)行期動(dòng)態(tài)綁定(通過虛函數(shù)表實(shí)現(xiàn))
  • 目的:實(shí)現(xiàn)多態(tài)(同一接口,不同實(shí)現(xiàn))

示例代碼

#include <iostream>
using namespace std;
class Shape {
public:
    // 基類中聲明為虛函數(shù)
    virtual void draw() { cout << "繪制圖形" << endl; }
};
class Circle : public Shape {
public:
    // 重寫基類的 draw 函數(shù),用 override 顯式標(biāo)注
    void draw() override { cout << "繪制圓形" << endl; }
};
class Rectangle : public Shape {
public:
    void draw() override { cout << "繪制矩形" << endl; }
};
int main() {
    Shape* shape1 = new Circle();
    Shape* shape2 = new Rectangle();
    // 運(yùn)行時(shí)根據(jù)實(shí)際對(duì)象類型調(diào)用對(duì)應(yīng)函數(shù)(多態(tài))
    shape1->draw();  // 輸出:繪制圓形
    shape2->draw();  // 輸出:繪制矩形
    delete shape1;
    delete shape2;
    return 0;
}

注意事項(xiàng)

  • 若派生類函數(shù)簽名與基類虛函數(shù)不一致,override 會(huì)導(dǎo)致編譯錯(cuò)誤(幫助開發(fā)者發(fā)現(xiàn)拼寫或參數(shù)錯(cuò)誤)
  • 基類虛函數(shù)被重寫后,派生類的函數(shù)默認(rèn)也是虛函數(shù)(即使不加 virtual
  • 重寫的函數(shù)返回值類型必須與基類一致(協(xié)變返回類型除外,如基類返回 Shape*,派生類返回 Circle*

三、函數(shù)隱藏(Hide)

? 定義

當(dāng)派生類中定義了一個(gè)與基類同名函數(shù)時(shí),若該函數(shù)不是重寫(即基類函數(shù)非虛函數(shù),或參數(shù)簽名不同),則派生類的函數(shù)會(huì) “隱藏” 基類中所有同名函數(shù) —— 即基類的同名函數(shù)在派生類中不可見,除非顯式調(diào)用。

?? 核心特性

  • 作用域:派生類與基類之間
  • 觸發(fā)條件
    • 基類函數(shù)未聲明為 virtual,派生類定義同名函數(shù)(無論參數(shù)是否相同)
    • 基類函數(shù)是虛函數(shù),但派生類函數(shù)參數(shù)簽名與基類不同
  • 綁定方式:編譯期靜態(tài)綁定
  • 效果:派生類中無法直接調(diào)用被隱藏的基類函數(shù),需用 基類名::函數(shù)名 顯式調(diào)用

示例代碼

#include <iostream>
using namespace std;
class Base {
public:
    void func(int x) { cout << "Base::func(int): " << x << endl; }
    void func(string s) { cout << "Base::func(string): " << s << endl; }
};
class Derived : public Base {
public:
    // 派生類定義同名函數(shù),參數(shù)類型不同(隱藏基類所有 func 函數(shù))
    void func(double x) { cout << "Derived::func(double): " << x << endl; }
};
int main() {
    Derived d;
    d.func(3.14);    // 調(diào)用 Derived::func(double)
    // d.func(10);    // 編譯錯(cuò)誤:基類的 func(int) 被隱藏
    // d.func("hi");  // 編譯錯(cuò)誤:基類的 func(string) 被隱藏
    // 顯式調(diào)用基類被隱藏的函數(shù)
    d.Base::func(10);      // 輸出:Base::func(int): 10
    d.Base::func("hi");    // 輸出:Base::func(string): hi
    return 0;
}

如何避免隱藏?

若希望在派生類中同時(shí)保留基類的同名函數(shù),可使用 using 聲明引入基類函數(shù):

class Derived : public Base {
public:
    using Base::func;  // 引入基類所有 func 重載函數(shù)
    void func(double x) { cout << "Derived::func(double): " << x << endl; }
};
// 此時(shí)可正常調(diào)用基類的 func 函數(shù)
int main() {
    Derived d;
    d.func(10);       // 調(diào)用 Base::func(int)
    d.func("hi");     // 調(diào)用 Base::func(string)
    d.func(3.14);     // 調(diào)用 Derived::func(double)
    return 0;
}

四、虛函數(shù)表(vtable):重寫的底層實(shí)現(xiàn)

重寫的核心是多態(tài),而多態(tài)的底層依賴于虛函數(shù)表(vtable) 和虛指針(vptr) 機(jī)制。以下是其工作原理:

1. 虛函數(shù)表的本質(zhì)

  • vtable:每個(gè)包含虛函數(shù)的類(或其派生類)會(huì)在編譯期生成一個(gè)虛函數(shù)表,這是一個(gè)存儲(chǔ)函數(shù)指針的數(shù)組,其中存放著該類所有虛函數(shù)的地址。
  • vptr:每個(gè)類的實(shí)例對(duì)象會(huì)包含一個(gè)虛指針(通常是對(duì)象的第一個(gè)成員),指向該類的 vtable。

2. 實(shí)現(xiàn)過程(以之前的Shape類為例)

  • 基類 Shape:

    • 編譯期生成 vtable,包含 Shape::draw() 的地址。
    • 每個(gè) Shape 對(duì)象有一個(gè) vptr,指向 Shape 的 vtable。
  • 派生類 Circle:

    • 繼承 Shape 的 vtable,但會(huì)用 Circle::draw() 的地址覆蓋 vtable 中 Shape::draw() 的位置。
    • 每個(gè) Circle 對(duì)象的 vptr 指向 Circle 的 vtable(而非 Shape 的)。
  • 調(diào)用時(shí)的動(dòng)態(tài)綁定:

    • 當(dāng)執(zhí)行 shape1->draw() 時(shí),編譯器無法確定 shape1 指向的是 Shape 還是 Circle 對(duì)象。
    • 實(shí)際執(zhí)行時(shí),程序通過 shape1 的 vptr 找到對(duì)應(yīng)的 vtable,再調(diào)用表中 draw() 函數(shù)的地址 —— 若 shape1 指向 Circle 對(duì)象,則調(diào)用 Circle::draw()。

3. 虛函數(shù)表的特性

  • 每個(gè)類只有一個(gè) vtable:所有實(shí)例共享同一個(gè) vtable(節(jié)省內(nèi)存)。
  • 派生類 vtable 包含基類虛函數(shù):若派生類未重寫基類虛函數(shù),則 vtable 中仍保留基類函數(shù)的地址。
  • 動(dòng)態(tài)綁定的開銷:相比普通函數(shù)調(diào)用,虛函數(shù)調(diào)用需多一次 “通過 vptr 查找 vtable” 的操作,效率略低(但通??珊雎裕?。

五、三者對(duì)比一覽表

特性重載(Overload)重寫(Override)隱藏(Hide)
作用域同一類 / 命名空間派生類與基類之間派生類與基類之間
函數(shù)關(guān)系同名不同參同名同參(基類為虛函數(shù))同名(參數(shù)不同或基類非虛函數(shù))
與繼承的關(guān)系必須繼承必須繼承
虛函數(shù)要求無需基類必須聲明 virtual基類通常非虛函數(shù)
綁定方式編譯期靜態(tài)綁定運(yùn)行期動(dòng)態(tài)綁定(vtable)編譯期靜態(tài)綁定
核心目的提供多版本函數(shù)接口實(shí)現(xiàn)多態(tài)(同一接口不同實(shí)現(xiàn))屏蔽基類同名函數(shù)
調(diào)用方式直接調(diào)用,編譯器自動(dòng)匹配通過基類指針 / 引用調(diào)用派生類對(duì)象直接調(diào)用派生類函數(shù),基類需顯式調(diào)用

六、記憶口訣與實(shí)戰(zhàn)建議

記憶口訣

  • 重載:同域同名,參數(shù)不同,編譯匹配。
  • 重寫:繼承虛函,簽名相同,運(yùn)行多態(tài)。
  • 隱藏:繼承同名,非重寫則藏,顯式調(diào)用。

實(shí)戰(zhàn)建議

  1. 用 override 標(biāo)注重寫:明確意圖,讓編譯器檢查簽名是否正確,避免意外隱藏。
  2. 避免同名函數(shù)在派生類中隨意定義:若無需重寫,盡量不要定義與基類同名的函數(shù)。
  3. 必要時(shí)用 using 引入基類函數(shù):當(dāng)需要在派生類中保留基類同名函數(shù)時(shí),用 using 顯式引入。
  4. 理解虛函數(shù)表機(jī)制:不僅能幫你掌握多態(tài)的本質(zhì),還能在調(diào)試復(fù)雜繼承關(guān)系時(shí)快速定位問題。

結(jié)語

掌握重載、重寫和隱藏的差異,是學(xué)好 C++ 面向?qū)ο缶幊痰幕A(chǔ)。其中,重寫與虛函數(shù)表機(jī)制更是 C++ 多態(tài)的核心,理解其底層原理能讓你在設(shè)計(jì)類層次結(jié)構(gòu)時(shí)更加得心應(yīng)手。記?。赫Z法是表象,機(jī)制是本質(zhì),只有透過現(xiàn)象看本質(zhì),才能真正掌握這些概念。

到此這篇關(guān)于C++中重載、重寫與隱藏從語法到底層實(shí)現(xiàn)的文章就介紹到這了,更多相關(guān)C++ 重載、重寫與隱藏內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • 深入解析C++編程中的純虛函數(shù)和抽象類

    深入解析C++編程中的純虛函數(shù)和抽象類

    這篇文章主要介紹了深入解析C++編程中的純虛函數(shù)和抽象類,是C++入門學(xué)習(xí)中的基礎(chǔ)知識(shí),需要的朋友可以參考下
    2015-09-09
  • 使用boost讀取XML文件詳細(xì)介紹

    使用boost讀取XML文件詳細(xì)介紹

    這篇文章主要介紹了使用boost讀取XML文件詳細(xì)介紹的相關(guān)資料,需要的朋友可以參考下
    2016-11-11
  • C語言實(shí)現(xiàn)貪吃蛇小游戲開發(fā)

    C語言實(shí)現(xiàn)貪吃蛇小游戲開發(fā)

    這篇文章主要為大家詳細(xì)介紹了C語言實(shí)現(xiàn)貪吃蛇小游戲開發(fā),文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2022-08-08
  • 在std::thread中創(chuàng)建并管理QEventLoop的全面解析

    在std::thread中創(chuàng)建并管理QEventLoop的全面解析

    QEventLoop的工作原理可以簡單地理解為一個(gè)無限循環(huán),它會(huì)不斷地檢查是否有新的事件需要處理,如果有,就將事件從事件隊(duì)列中取出,然后找到相應(yīng)的事件處理器進(jìn)行處理,這篇文章主要介紹了在std::thread中創(chuàng)建并管理QEventLoop的全面指南,需要的朋友可以參考下
    2023-06-06
  • 從入門到精通C++11?<chrono>?庫特性

    從入門到精通C++11?<chrono>?庫特性

    chrono庫是C++11中一個(gè)非常強(qiáng)大和實(shí)用的庫,它為時(shí)間處理提供了豐富的功能和類型安全的接口,通過本文的介紹,我們了解了chrono庫的基本概念,感興趣的朋友一起看看吧
    2025-06-06
  • C++中取余運(yùn)算的實(shí)現(xiàn)

    C++中取余運(yùn)算的實(shí)現(xiàn)

    這篇文章主要介紹了C++中取余運(yùn)算的實(shí)現(xiàn),文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2021-02-02
  • C 語言restrict 關(guān)鍵字的使用淺談

    C 語言restrict 關(guān)鍵字的使用淺談

    C 語言restrict 關(guān)鍵字的使用淺談,需要的朋友可以參考一下
    2013-04-04
  • 深入理解Java事務(wù)的原理與應(yīng)用

    深入理解Java事務(wù)的原理與應(yīng)用

    下面小編就為大家?guī)硪黄钊肜斫釰ava事務(wù)的原理與應(yīng)用。小編覺得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧
    2016-06-06
  • Qt中Tab與Tree組件實(shí)現(xiàn)分頁菜單

    Qt中Tab與Tree組件實(shí)現(xiàn)分頁菜單

    本文主要介紹tabWidget選擇夾組件與TreeWidget樹形選擇組件的常用方法及靈活運(yùn)用,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2023-12-12
  • 詳解C++中的菱形繼承問題

    詳解C++中的菱形繼承問題

    這篇文章主要介紹了詳解C++中的菱形繼承問題,在多繼承結(jié)構(gòu)中,存在著很多問題,比如從不同基類中繼承了同名成員,派生類中也定義了同名成員,這種二義性問題很好解決,加上要訪問的基類的類名限制就可以了,需要的朋友可以參考下
    2023-08-08

最新評(píng)論

焦作市| 宜春市| 兴隆县| 南岸区| 元朗区| 日照市| 新田县| 区。| 遵化市| 木里| 余庆县| 大竹县| 山阴县| 蚌埠市| 汪清县| 河间市| 朝阳区| 和硕县| 新龙县| 成武县| 安义县| 东丽区| 宾川县| 昭觉县| 河曲县| 泽库县| 玉林市| 昌图县| 浑源县| 南漳县| 长春市| 宁阳县| 成都市| 阿鲁科尔沁旗| 专栏| 陇南市| 武平县| 噶尔县| 商河县| 织金县| 黔西县|