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

C++中構(gòu)造函數(shù)的初始化順序說明

 更新時間:2025年07月29日 16:52:08   作者:Littlewith  
C++構(gòu)造函數(shù)調(diào)用遵循基類→成員對象→派生類順序,虛函數(shù)在構(gòu)造中靜態(tài)綁定,完成后動態(tài)綁定,拷貝構(gòu)造在初始化、賦值及容器操作時調(diào)用,RVO優(yōu)化可能避免拷貝,虛函數(shù)重寫自子類起生效,不追溯基類

關(guān)鍵規(guī)則

  • 如果派生類有基類(單繼承或多繼承),基類的構(gòu)造函數(shù)會首先被調(diào)用。

對基類進(jìn)行處理

  • 多繼承時,按照派生類繼承列表中聲明的順序(從左到右)依次調(diào)用基類的構(gòu)造函數(shù)。
  • 如果有虛繼承,虛基類的構(gòu)造函數(shù)優(yōu)先于非虛基類調(diào)用,且只調(diào)用一次
  • 虛基類只在最遠(yuǎn)派生類中進(jìn)行處理,并且只有最遠(yuǎn)派生類調(diào)用,其他虛繼承的派生類調(diào)用被忽略,并且只執(zhí)行一次

對成員對象進(jìn)行處理

  • 在基類構(gòu)造函數(shù)調(diào)用完成后,派生類中聲明的成員對象的構(gòu)造函數(shù)會被調(diào)用。
  • 成員對象的構(gòu)造順序遵循它們在類中聲明的順序(而不是初始化列表中的順序)。
  • 如果成員對象有自己的構(gòu)造函數(shù),C++ 會根據(jù)初始化列表(如果提供)或默認(rèn)構(gòu)造函數(shù)來調(diào)用。

派生類自己的構(gòu)造函數(shù)

  • 最后,派生類自己的構(gòu)造函數(shù)體被執(zhí)行。

特殊情況

如果父類構(gòu)造函數(shù)含有虛函數(shù)調(diào)用

  • 在父類的構(gòu)造函數(shù)中調(diào)用虛函數(shù),還是會執(zhí)行父類的構(gòu)造函數(shù),不會跑到子類中去,即使有vitual,因?yàn)榇藭r父類都還沒有構(gòu)造完成,子類也就還沒有構(gòu)造。
#include <iostream>
using namespace std;
 
class A{
  public:
    A ():m_iVal(0){test();}//這里的test會調(diào)用父類的virtual void func()
    virtual void func() { std::cout<<m_iVal<<' ';}
    void test(){func();}
  public:
      int m_iVal;
};
class B : public A{
  public:
    B(){test();}//這里的test會調(diào)用父類的test()進(jìn)而通過指針匹配
    virtual void func(){
      ++m_iVal;
      std::cout << m_iVal << ' ';
      }
};
int main(int argc ,char* argv[]){
  A*p = new B;
  p->test();
  return 0;
}

輸出結(jié)果

0 1 2

虛函數(shù)調(diào)用規(guī)則

  • 構(gòu)造函數(shù)中:綁定到當(dāng)前構(gòu)造的類版本。
  • 構(gòu)造完成后:動態(tài)綁定到實(shí)際對象類型。

執(zhí)行流程

  • A::A() → test() → A::func() → 輸出0(vtable指向A)。
  • B::B() → test() → B::func() → m_iVal++,輸出1(vtable指向B)。
  • p->test() → B::func() → m_iVal++,輸出2。

vtable切換

  • 基類構(gòu)造:指向A。
  • 基類完成后,進(jìn)入B::B()前:指向B。

輸出

0 1 2。

核心結(jié)論

  • 構(gòu)造函數(shù)中虛函數(shù)調(diào)用取決于當(dāng)前類類型,非最終類型。
  • vtable在基類構(gòu)造后、派生類構(gòu)造函數(shù)體前更新。
  • 注意:在執(zhí)行構(gòu)造函數(shù)體之前,可以認(rèn)為構(gòu)造函數(shù)**已經(jīng)完全完成了相應(yīng)對象的初始化工作,**在C++的實(shí)現(xiàn)中,虛函數(shù)表的切換發(fā)生在進(jìn)入派生類構(gòu)造函數(shù)體之前,而不是等到整個構(gòu)造函數(shù)結(jié)束。

關(guān)于拷貝構(gòu)造函數(shù)的初始化問題

  • 在初始化時如果對象不存在,且沒有聲明explict禁用賦值操作
  • 編譯器默認(rèn)調(diào)用拷貝構(gòu)造函數(shù)
#include<iostream>
using namespace std;

class MyClass {
public:
    MyClass(int i = 0) { // 構(gòu)造函數(shù)
        cout << i;
    }
    MyClass(const MyClass &x) { // 拷貝構(gòu)造函數(shù)
        cout << 2;
    }
    MyClass &operator=(const MyClass &x) { // 賦值運(yùn)算符
        cout << 3;
        return *this;
    }
    ~MyClass() { // 析構(gòu)函數(shù)
        cout << 4;
    }
};

int main() {
    MyClass obj1(1), obj2(2); // 創(chuàng)建 obj1 和 obj2
    MyClass obj3 = obj1;      // 創(chuàng)建 obj3 并初始化
    return 0;
}
MyClass obj3 = obj1;

由于obj3為被創(chuàng)建,那么調(diào)用拷貝構(gòu)造函數(shù),稱為復(fù)制初始化

MyClass obj3; // 先默認(rèn)構(gòu)造
obj3 = obj1; // 再賦值

這時會導(dǎo)致調(diào)用賦值運(yùn)算符

拷貝構(gòu)造函數(shù)的什么時候被調(diào)用呢?

場景示例代碼說明
對象初始化MyClass b = a;或者M(jìn)yClass b(a);用已有對象初始化新對象
按值傳遞參數(shù)void func(MyClass x);函數(shù)參數(shù)創(chuàng)建副本
按值返回對象MyClass func() { … }返回局部對象(可能被優(yōu)化,現(xiàn)如今的C++編譯器普遍采用了RVO返回值優(yōu)化導(dǎo)致返回時候不會進(jìn)行拷貝)
容器操作vec.push_back(a);插入對象到容器
顯式調(diào)用new MyClass(a);動態(tài)分配時拷貝

關(guān)于子類和父類的虛函數(shù)問題

如果父類函數(shù)不是 virtual,子類將其聲明為 virtual:

  • 對基類無影響,基類調(diào)用仍是靜態(tài)綁定。
  • 從子類開始,函數(shù)成為虛函數(shù),后續(xù)派生類可以實(shí)現(xiàn)多態(tài),(即便是后續(xù)沒有加virtual關(guān)鍵字也是多態(tài))
#include <iostream>
class Base {
public:
    void foo() { // 非虛函數(shù)
        std::cout << "Base::foo()" << std::endl;
    }
};

class Derived : public Base {
public:
    virtual void foo() { // 子類聲明為虛函數(shù)
        std::cout << "Derived::foo()" << std::endl;
    }
};

class GrandDerived : public Derived {
public:
    void foo() { // 重寫 Derived 中的虛函數(shù)
        std::cout << "GrandDerived::foo()" << std::endl;
    }
};

int main() {
    Base* b1 = new Derived();
    b1->foo(); // 輸出 "Base::foo()"

    Derived* d1 = new Derived();
    d1->foo(); // 輸出 "Derived::foo()"

    Base* b2 = new GrandDerived();
    b2->foo(); // 輸出 "Base::foo()"

    Derived* d2 = new GrandDerived();
    d2->foo(); // 輸出 "GrandDerived::foo()"
    delete b1; delete d1; delete b2; delete d2;
    return 0;
}

父類函數(shù)非虛,沒有多態(tài)

  • 因?yàn)?Base::foo() 不是虛函數(shù),通過 Base* 指針調(diào)用 foo() 時**,總是執(zhí)行 Base::foo()**,不會發(fā)生運(yùn)行時多態(tài)。
  • 即使 Derived::foo() 被聲明為 virtual,它對 Base 的函數(shù)沒有影響,因?yàn)槎鄳B(tài)性需要從基類開始啟用。

子類聲明為虛,影響后續(xù)繼承

  • 在 Derived 中將 foo() 聲明為 virtual,意味著從 Derived 開始,這個函數(shù)變成了虛函數(shù)。
  • 后續(xù)的派生類(如 GrandDerived)可以重寫 Derived::foo(),并通過 Derived* 或 Derived& 調(diào)用時實(shí)現(xiàn)多態(tài)。
  • 但這種多態(tài)僅限于 Derived 及其子類,不追溯到 Base。

隱藏而非重寫

  • Derived::foo() 只是隱藏了 Base::foo(),而不是重寫它。
  • 當(dāng)通過 Base* 調(diào)用時,調(diào)用的仍然是 Base::foo(),因?yàn)?Base::foo() 不是虛函數(shù)。

總結(jié)

以上為個人經(jīng)驗(yàn),希望能給大家一個參考,也希望大家多多支持腳本之家。

相關(guān)文章

  • 使用Qt生成Word和PDF文檔的詳細(xì)教程

    使用Qt生成Word和PDF文檔的詳細(xì)教程

    Qt 是一個跨平臺的應(yīng)用程序開發(fā)框架,除了用于創(chuàng)建圖形界面應(yīng)用程序外,還可以用來生成 Word 和 PDF 文檔,本文將介紹如何使用 Qt 來生成Word和PDF文檔,以及相關(guān)的代碼示例,需要的朋友可以參考下
    2023-10-10
  • 利用Qt實(shí)現(xiàn)網(wǎng)絡(luò)數(shù)據(jù)報文大小端數(shù)據(jù)的收發(fā)

    利用Qt實(shí)現(xiàn)網(wǎng)絡(luò)數(shù)據(jù)報文大小端數(shù)據(jù)的收發(fā)

    大小端(Endianness)是計(jì)算機(jī)體系結(jié)構(gòu)的一個術(shù)語,它描述了多字節(jié)數(shù)據(jù)在內(nèi)存中的存儲順序,下面我們來看看如何利用Qt實(shí)現(xiàn)網(wǎng)絡(luò)數(shù)據(jù)報文大小端數(shù)據(jù)的收發(fā)吧
    2024-11-11
  • C++關(guān)鍵字const使用方法詳解

    C++關(guān)鍵字const使用方法詳解

    C語言中的const與C++有很大的不同,在C語言中用const修飾的變量仍是一個變量,表示這個變量是只讀的,不可顯示地更改,C++中的const關(guān)鍵字的用法非常靈活,而使用const將大大改善程序的健壯性,const關(guān)鍵字是一種修飾符
    2022-12-12
  • C++中字符串的查找與插入方式

    C++中字符串的查找與插入方式

    本文介紹了三種查找子字符串的方法,包括暴力匹配、使用函數(shù)和使用循環(huán),同時,介紹了三種插入內(nèi)容的方法,包括直接插入、使用substr截取和使用for循環(huán)逐個字符拼接,最后強(qiáng)調(diào)了這些方法僅為個人經(jīng)驗(yàn),希望能提供參考
    2026-04-04
  • C語言 遞歸解決青蛙跳臺階問題

    C語言 遞歸解決青蛙跳臺階問題

    遞歸做為一種算法在程序設(shè)計(jì)語言中廣泛應(yīng)用?;竞x&#8203;是指函數(shù)/過程/子程序在運(yùn)行過程序中直接或間接調(diào)用自身而產(chǎn)生的重入現(xiàn)象。在計(jì)算機(jī)編程里,遞歸指的是一個過程:函數(shù)不斷引用自身,直到引用的對象已知
    2021-11-11
  • C++制作簡單的計(jì)算器功能

    C++制作簡單的計(jì)算器功能

    這篇文章主要為大家詳細(xì)介紹了C++制作簡單的計(jì)算器功能,文中示例代碼介紹的非常詳細(xì),具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2022-02-02
  • C++示例講解string容器

    C++示例講解string容器

    c++相比c的一個好處就是實(shí)現(xiàn)了很多的容器和泛型算法,使得程序員的工作得到了很大的簡化,本文重點(diǎn)給大家介紹C++string容器基本概念講解,需要的朋友參考下吧
    2022-07-07
  • 深入了解C語言字符函數(shù)和字符串函數(shù)

    深入了解C語言字符函數(shù)和字符串函數(shù)

    這篇文章主要給大家介紹了關(guān)于C語言字符/字符串的相關(guān)函數(shù),文中通過示例代碼總結(jié)的非常詳細(xì),對大家學(xué)習(xí)或者使用C語言具有一定的參考學(xué)習(xí)價值,需要的朋友們下面來一起學(xué)習(xí)學(xué)習(xí)吧
    2021-07-07
  • C語言Easyx實(shí)現(xiàn)貪吃蛇詳解

    C語言Easyx實(shí)現(xiàn)貪吃蛇詳解

    這篇文章主要為大家詳細(xì)介紹了基于easyx的C++實(shí)現(xiàn)貪吃蛇,文中示例代碼介紹的非常詳細(xì),具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2021-10-10
  • Qt自定義實(shí)現(xiàn)一個等待提示Ui控件

    Qt自定義實(shí)現(xiàn)一個等待提示Ui控件

    等待樣式控件是我們在做UI時出場率還挺高的控件之一,所以這篇文章主要為大家介紹了Qt如何自定義一個好看的等待提示Ui控件,感興趣的可以了解下
    2024-01-01

最新評論

新泰市| 通城县| 晋城| 绥滨县| 教育| 图木舒克市| 五大连池市| 保靖县| 安图县| 琼结县| 阳东县| 丰原市| 眉山市| 曲阳县| 汕尾市| 南涧| 马尔康县| 静乐县| 诏安县| 邻水| 九龙城区| 五原县| 瑞昌市| 双牌县| 渭源县| 长岛县| 灵川县| 琼海市| 龙里县| 陵水| 崇阳县| 遂溪县| 宝兴县| 福海县| 墨竹工卡县| 奉节县| 基隆市| 社会| 平山县| 河西区| 大同县|