日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 编程语言 > c/c++ >内容正文

c/c++

C++ 向上转型

發(fā)布時(shí)間:2025/3/12 c/c++ 26 豆豆
生活随笔 收集整理的這篇文章主要介紹了 C++ 向上转型 小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

在 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ù)。

將派生類對(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ù)不存在賦值問(wèn)題。

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

可以發(fā)現(xiàn),即使將派生類對(duì)象賦值給基類對(duì)象,基類對(duì)象也不會(huì)包含派生類的成員,所以依然不同通過(guò)基類對(duì)象來(lái)訪問(wèn)派生類的成員。

這種轉(zhuǎn)換關(guān)系是不可逆的,只能用派生類對(duì)象給基類對(duì)象賦值,而不能用基類對(duì)象給派生類對(duì)象賦值

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

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


下面的代碼實(shí)現(xiàn)了這種繼承關(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ì)象指針之間的賦值并沒(méi)有拷貝對(duì)象的成員,也沒(méi)有修改對(duì)象本身的數(shù)據(jù),僅僅是改變了指針的指向。

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

引用在本質(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ì)象的成員變量,但是卻沒(méi)有使用派生類的成員函數(shù),這和指針的表現(xiàn)是一樣的。

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

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

總結(jié)

以上是生活随笔為你收集整理的C++ 向上转型的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

如果覺(jué)得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。