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

基于C/C++將派生類賦值給基類的超詳細(xì)講解

 更新時(shí)間:2023年06月16日 15:50:17   作者:阿玥的小東東  
類其實(shí)也是一種數(shù)據(jù)類型,也可以發(fā)生數(shù)據(jù)類型轉(zhuǎn)換,下面這篇文章主要給大家介紹了關(guān)于基于C/C++將派生類賦值給基類的超詳細(xì)講解,文中通過(guò)實(shí)例代碼介紹的非常詳細(xì),需要的朋友可以參考下

前言

在 C/C++中經(jīng)常會(huì)發(fā)生數(shù)據(jù)類型的轉(zhuǎn)換,例如將 int 類型的數(shù)據(jù)賦值給 float 類型的變量時(shí),編譯器會(huì)先把 int 類型的數(shù)據(jù)轉(zhuǎn)換為 float 類型再賦值;反過(guò)來(lái),float 類型的數(shù)據(jù)在經(jīng)過(guò)類型轉(zhuǎn)換后也可以賦值給 int 類型的變量。

數(shù)據(jù)類型轉(zhuǎn)換的前提是,編譯器知道如何對(duì)數(shù)據(jù)進(jìn)行取舍。例如:

int a = 10.9;
printf("%d\n", a);

 輸出結(jié)果為 10,編譯器會(huì)將小數(shù)部分直接丟掉(不是四舍五入)。再如:

float b = 10;
printf("%f\n", b);

輸出結(jié)果為 10.000000,編譯器會(huì)自動(dòng)添加小數(shù)部分。

類其實(shí)也是一種數(shù)據(jù)類型,也可以發(fā)生數(shù)據(jù)類型轉(zhuǎn)換,不過(guò)這種轉(zhuǎn)換只有在基類和派生類之間才有意義,并且只能將派生類賦值給基類,包括將派生類對(duì)象賦值給基類對(duì)象、將派生類指針賦值給基類指針、將派生類引用賦值給基類引用,這在 C++ 中稱為向上轉(zhuǎn)型(Upcasting)。相應(yīng)地,將基類賦值給派生類稱為向下轉(zhuǎn)型(Downcasting)。

向上轉(zhuǎn)型非常安全,可以由編譯器自動(dòng)完成;向下轉(zhuǎn)型有風(fēng)險(xiǎn),需要程序員手動(dòng)干預(yù)。本節(jié)只介紹向上轉(zhuǎn)型,向下轉(zhuǎn)型將在后續(xù)章節(jié)介紹。

向上轉(zhuǎn)型和向下轉(zhuǎn)型是面向?qū)ο缶幊痰囊环N通用概念,它們也存在于 Java、C#等編程語(yǔ)言中。

將派生類對(duì)象賦值給基類對(duì)象

下面的例子演示了如何將派生類對(duì)象賦值給基類對(duì)象:

#include <iostream>
using namespace std;
 
//基類
class A{
public:
    A(int a);
public:
    void display();
public:
    int m_a;
};
A::A(int a): m_a(a){ }
void A::display(){
    cout<<"Class A: m_a="<<m_a<<endl;
}
 
//派生類
class B: public A{
public:
    B(int a, int b);
public:
    void display();
public:
    int m_b;
};
B::B(int a, int b): A(a), m_b(b){ }
void B::display(){
    cout<<"Class B: m_a="<<m_a<<", m_b="<<m_b<<endl;
}
 
int main(){
    A a(10);
    B b(66, 99);
    //賦值前
    a.display();
    b.display();
    cout<<"--------------"<<endl;
    //賦值后
    a = b;
    a.display();
    b.display();
 
    return 0;
}

運(yùn)行結(jié)果:

Class A: m_a=10
Class B: m_a=66, m_b=99
----------------------------
Class A: m_a=66
Class B: m_a=66, m_b=99

本例中 A 是基類, B 是派生類,a、b 分別是它們的對(duì)象,由于派生類 B 包含了從基類 A 繼承來(lái)的成員,因此可以將派生類對(duì)象 b 賦值給基類對(duì)象 a。通過(guò)運(yùn)行結(jié)果也可以發(fā)現(xiàn),賦值后 a 所包含的成員變量的值已經(jīng)發(fā)生了變化。

賦值的本質(zhì)是將現(xiàn)有的數(shù)據(jù)寫入已分配好的內(nèi)存中,對(duì)象的內(nèi)存只包含了成員變量,所以對(duì)象之間的賦值是成員變量的賦值,成員函數(shù)不存在賦值問題。運(yùn)行結(jié)果也有力地證明了這一點(diǎn),雖然有a=b;這樣的賦值過(guò)程,但是 a.display() 始終調(diào)用的都是 A 類的 display() 函數(shù)。換句話說(shuō),對(duì)象之間的賦值不會(huì)影響成員函數(shù),也不會(huì)影響 this 指針。

將派生類對(duì)象賦值給基類對(duì)象時(shí),會(huì)舍棄派生類新增的成員,也就是“大材小用”,如下圖所示:

 可以發(fā)現(xiàn),即使將派生類對(duì)象賦值給基類對(duì)象,基類對(duì)象也不會(huì)包含派生類的成員,所以依然不同通過(guò)基類對(duì)象來(lái)訪問派生類的成員。對(duì)于上面的例子,a.m_a 是正確的,但 a.m_b 就是錯(cuò)誤的,因?yàn)?a 不包含成員 m_b。

這種轉(zhuǎn)換關(guān)系是不可逆的,只能用派生類對(duì)象給基類對(duì)象賦值,而不能用基類對(duì)象給派生類對(duì)象賦值。理由很簡(jiǎn)單,基類不包含派生類的成員變量,無(wú)法對(duì)派生類的成員變量賦值。同理,同一基類的不同派生類對(duì)象之間也不能賦值。

要理解這個(gè)問題,還得從賦值的本質(zhì)入手。賦值實(shí)際上是向內(nèi)存填充數(shù)據(jù),當(dāng)數(shù)據(jù)較多時(shí)很好處理,舍棄即可;本例中將 b 賦值給 a 時(shí)(執(zhí)行a=b;語(yǔ)句),成員 m_b 是多余的,會(huì)被直接丟掉,所以不會(huì)發(fā)生賦值錯(cuò)誤。但當(dāng)數(shù)據(jù)較少時(shí),問題就很棘手,編譯器不知道如何填充剩下的內(nèi)存;如果本例中有b= a;這樣的語(yǔ)句,編譯器就不知道該如何給變量 m_b 賦值,所以會(huì)發(fā)生錯(cuò)誤。

將派生類指針賦值給基類指針

除了可以將派生類對(duì)象賦值給基類對(duì)象(對(duì)象變量之間的賦值),還可以將派生類指針賦值給基類指針(對(duì)象指針之間的賦值)。我們先來(lái)看一個(gè)多繼承的例子,繼承關(guān)系為:

#include <iostream>
using namespace std;
 
//基類A
class A{
public:
    A(int a);
public:
    void display();
protected:
    int m_a;
};
A::A(int a): m_a(a){ }
void A::display(){
    cout<<"Class A: m_a="<<m_a<<endl;
}
 
//中間派生類B
class B: public A{
public:
    B(int a, int b);
public:
    void display();
protected:
    int m_b;
};
B::B(int a, int b): A(a), m_b(b){ }
void B::display(){
    cout<<"Class B: m_a="<<m_a<<", m_b="<<m_b<<endl;
}
 
//基類C
class C{
public:
    C(int c);
public:
    void display();
protected:
    int m_c;
};
C::C(int c): m_c(c){ }
void C::display(){
    cout<<"Class C: m_c="<<m_c<<endl;
}
 
//最終派生類D
class D: public B, public C{
public:
    D(int a, int b, int c, int d);
public:
    void display();
private:
    int m_d;
};
D::D(int a, int b, int c, int d): B(a, b), C(c), m_d(d){ }
void D::display(){
    cout<<"Class D: m_a="<<m_a<<", m_b="<<m_b<<", m_c="<<m_c<<", m_d="<<m_d<<endl;
}
 
int main(){
    A *pa = new A(1);
    B *pb = new B(2, 20);
    C *pc = new C(3);
    D *pd = new D(4, 40, 400, 4000);
 
    pa = pd;
    pa -> display();
 
    pb = pd;
    pb -> display();
 
    pc = pd;
    pc -> display();
 
    cout<<"-----------------------"<<endl;
    cout<<"pa="<<pa<<endl;
    cout<<"pb="<<pb<<endl;
    cout<<"pc="<<pc<<endl;
    cout<<"pd="<<pd<<endl;
 
    return 0;
}

運(yùn)行結(jié)果:
Class A: m_a=4
Class B: m_a=4, m_b=40
Class C: m_c=400
-----------------------
pa=0x9b17f8
pb=0x9b17f8
pc=0x9b1800
pd=0x9b17f8

本例中定義了多個(gè)對(duì)象指針,并嘗試將派生類指針賦值給基類指針。與對(duì)象變量之間的賦值不同的是,對(duì)象指針之間的賦值并沒有拷貝對(duì)象的成員,也沒有修改對(duì)象本身的數(shù)據(jù),僅僅是改變了指針的指向。

1) 通過(guò)基類指針訪問派生類的成員

請(qǐng)讀者先關(guān)注第 68 行代碼,我們將派生類指針 pd 賦值給了基類指針 pa,從運(yùn)行結(jié)果可以看出,調(diào)用 display() 函數(shù)時(shí)雖然使用了派生類的成員變量,但是 display() 函數(shù)本身卻是基類的。也就是說(shuō),將派生類指針賦值給基類指針時(shí),通過(guò)基類指針只能使用派生類的成員變量,但不能使用派生類的成員函數(shù),這看起來(lái)有點(diǎn)不倫不類,究竟是為什么呢?第 71、74 行代碼也是類似的情況。

pa 本來(lái)是基類 A 的指針,現(xiàn)在指向了派生類 D 的對(duì)象,這使得隱式指針 this 發(fā)生了變化,也指向了 D 類的對(duì)象,所以最終在 display() 內(nèi)部使用的是 D 類對(duì)象的成員變量,相信這一點(diǎn)不難理解。

編譯器雖然通過(guò)指針的指向來(lái)訪問成員變量,但是卻不通過(guò)指針的指向來(lái)訪問成員函數(shù):編譯器通過(guò)指針的類型來(lái)訪問成員函數(shù)。對(duì)于 pa,它的類型是 A,不管它指向哪個(gè)對(duì)象,使用的都是 A 類的成員函數(shù)

概括起來(lái)說(shuō)就是:編譯器通過(guò)指針來(lái)訪問成員變量,指針指向哪個(gè)對(duì)象就使用哪個(gè)對(duì)象的數(shù)據(jù);編譯器通過(guò)指針的類型來(lái)訪問成員函數(shù),指針屬于哪個(gè)類的類型就使用哪個(gè)類的函數(shù)。

2) 賦值后值不一致的情況

本例中我們將最終派生類的指針 pd 分別賦值給了基類指針 pa、pb、pc,按理說(shuō)它們的值應(yīng)該相等,都指向同一塊內(nèi)存,但是運(yùn)行結(jié)果卻有力地反駁了這種推論,只有 pa、pb、pd 三個(gè)指針的值相等,pc 的值比它們都大。也就是說(shuō),執(zhí)行pc = pd;語(yǔ)句后,pc 和 pd 的值并不相等。

將派生類引用賦值給基類引用

引用在本質(zhì)上是通過(guò)指針的方式實(shí)現(xiàn)的,既然基類的指針可以指向派生類的對(duì)象,那么我們就有理由推斷:基類的引用也可以指向派生類的對(duì)象,并且它的表現(xiàn)和指針是類似的。

修改上例中 main() 函數(shù)內(nèi)部的代碼,用引用取代指針:

int main(){
    D d(4, 40, 400, 4000);
    A &ra = d;
    B &rb = d;
    C &rc = d;
    ra.display();
    rb.display();
    rc.display();
    return 0;
}

 運(yùn)行結(jié)果:
Class A: m_a=4
Class B: m_a=4, m_b=40
Class C: m_c=400

ra、rb、rc 是基類的引用,它們都引用了派生類對(duì)象 d,并調(diào)用了 display() 函數(shù),從運(yùn)行結(jié)果可以發(fā)現(xiàn),雖然使用了派生類對(duì)象的成員變量,但是卻沒有使用派生類的成員函數(shù),這和指針的表現(xiàn)是一樣的。

引用和指針的表現(xiàn)之所以如此類似,是因?yàn)橐煤椭羔槻]有本質(zhì)上的區(qū)別,引用僅僅是對(duì)指針進(jìn)行了簡(jiǎn)單封裝

最后需要注意的是,向上轉(zhuǎn)型后通過(guò)基類的對(duì)象、指針、引用只能訪問從基類繼承過(guò)去的成員(包括成員變量和成員函數(shù)),不能訪問派生類新增的成員。

總結(jié)

到此這篇關(guān)于基于C/C++將派生類賦值給基類的超詳細(xì)講解的文章就介紹到這了,更多相關(guān)C/C++將派生類賦值給基類內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • Qt圖片繪圖類之QPixmap/QImage/QPicture詳解

    Qt圖片繪圖類之QPixmap/QImage/QPicture詳解

    這篇文章主要為大家詳細(xì)介紹了Qt圖片繪圖類中QPixmap、QImage和QPicture的使用方法,文中的示例代碼講解詳細(xì),感興趣的小伙伴可以跟隨小編一起學(xué)習(xí)一下
    2023-03-03
  • C語(yǔ)言 指針與二維數(shù)組詳解

    C語(yǔ)言 指針與二維數(shù)組詳解

    本文主要介紹C語(yǔ)言 指針與二維數(shù)組,這里整理了詳細(xì)的資料及示例代碼,有需要的小伙伴可以參考下
    2016-08-08
  • 適合新手小白DEV?C++的使用方法

    適合新手小白DEV?C++的使用方法

    Dev-C++是一個(gè)Windows環(huán)境下C/C++的集成開發(fā)環(huán)境(IDE),它是一款自由軟件,遵守GPL,下面這篇文章主要給大家介紹了關(guān)于適合新手小白DEV?C++的使用方法,文中通過(guò)圖文介紹的非常詳細(xì),需要的朋友可以參考下
    2023-02-02
  • C++實(shí)現(xiàn)T型插補(bǔ)詳解

    C++實(shí)現(xiàn)T型插補(bǔ)詳解

    這篇文章主要介紹了C++實(shí)現(xiàn)T型插補(bǔ),本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2021-10-10
  • Windows配置Qt環(huán)境變量的全指南

    Windows配置Qt環(huán)境變量的全指南

    Qt是一個(gè)跨平臺(tái)C++開發(fā)框架,包含GUI、網(wǎng)絡(luò)、SQL、多媒體等模塊,安裝后自帶豐富工具鏈,若未正確配置環(huán)境變量會(huì)導(dǎo)致一系列問題,因此建議根據(jù)實(shí)際開發(fā)場(chǎng)景,合理設(shè)置局部或臨時(shí)Qt環(huán)境變量,實(shí)現(xiàn)靈活且可控的開發(fā)體驗(yàn),所以本文介紹了Windows配置Qt環(huán)境變量的全指南
    2025-07-07
  • C++實(shí)現(xiàn)LeetCode(172.求階乘末尾零的個(gè)數(shù))

    C++實(shí)現(xiàn)LeetCode(172.求階乘末尾零的個(gè)數(shù))

    這篇文章主要介紹了C++實(shí)現(xiàn)LeetCode(172.求階乘末尾零的個(gè)數(shù)),本篇文章通過(guò)簡(jiǎn)要的案例,講解了該項(xiàng)技術(shù)的了解與使用,以下就是詳細(xì)內(nèi)容,需要的朋友可以參考下
    2021-08-08
  • c++ vector(向量)使用方法詳解(順序訪問vector的多種方式)

    c++ vector(向量)使用方法詳解(順序訪問vector的多種方式)

    vector是向量類型,它可以容納許多類型的數(shù)據(jù),如若干個(gè)整數(shù),所以稱其為容器,本文介紹一下使用方法
    2013-12-12
  • C語(yǔ)言分支循環(huán)其嵌套語(yǔ)句的使用

    C語(yǔ)言分支循環(huán)其嵌套語(yǔ)句的使用

    本文主要介紹了switch 嵌套和循環(huán)嵌套,文中通過(guò)示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2021-11-11
  • 深入解析C語(yǔ)言中常數(shù)的數(shù)據(jù)類型

    深入解析C語(yǔ)言中常數(shù)的數(shù)據(jù)類型

    C語(yǔ)言中常數(shù)的數(shù)據(jù)類型,需要的朋友可以過(guò)來(lái)參考下。希望對(duì)大家有所幫助
    2013-10-10
  • C語(yǔ)言深入探索數(shù)據(jù)類型的存儲(chǔ)

    C語(yǔ)言深入探索數(shù)據(jù)類型的存儲(chǔ)

    使用編程語(yǔ)言進(jìn)行編程時(shí),需要用到各種變量來(lái)存儲(chǔ)各種信息。變量保留的是它所存儲(chǔ)的值的內(nèi)存位置。這意味著,當(dāng)您創(chuàng)建一個(gè)變量時(shí),就會(huì)在內(nèi)存中保留一些空間。您可能需要存儲(chǔ)各種數(shù)據(jù)類型的信息,操作系統(tǒng)會(huì)根據(jù)變量的數(shù)據(jù)類型,來(lái)分配內(nèi)存和決定在保留內(nèi)存中存儲(chǔ)什么
    2022-07-07

最新評(píng)論

胶南市| 榕江县| 固安县| 涟源市| 平乐县| 铜梁县| 怀集县| 乌恰县| 类乌齐县| 阳曲县| 平度市| 红桥区| 铜梁县| 手游| 广灵县| 神农架林区| 建湖县| 曲松县| 望奎县| 新巴尔虎右旗| 砀山县| 金乡县| 万安县| 开化县| 鹤峰县| 札达县| 双鸭山市| 邵阳县| 安达市| 滨州市| 北碚区| 茌平县| 深州市| 贵州省| 上栗县| 濉溪县| 都匀市| 横峰县| 临猗县| 河南省| 红桥区|