C++将派生类赋值给基类(向上转型)(一)
在 C/C++ 中經常會發生數據類型的轉換,例如將 int 類型的數據賦值給 float 類型的變量時,編譯器會先把 int 類型的數據轉換為 float 類型再賦值;反過來,float 類型的數據在經過類型轉換后也可以賦值給 int 類型的變量。
數據類型轉換的前提是,編譯器知道如何對數據進行取舍。例如:
int a = 10.9; printf("%d\n", a);輸出結果為 10,編譯器會將小數部分直接丟掉(不是四舍五入)。再如:
float b = 10; printf("%f\n", b);輸出結果為 10.000000,編譯器會自動添加小數部分。
#include "stdio.h"int main(){int a = 10.9;printf("%d\n", a);float b = 10;printf("%f\n", b);return 0; } 10 10.000000類其實也是一種數據類型,也可以發生數據類型轉換,不過這種轉換只有在基類和派生類之間才有意義,并且只能將派生類賦值給基類,包括將派生類對象賦值給基類對象、將派生類指針賦值給基類指針、將派生類引用賦值給基類引用,這在 C++ 中稱為向上轉型(Upcasting)。相應地,將基類賦值給派生類稱為向下轉型(Downcasting)。
向上轉型非常安全,可以由編譯器自動完成;向下轉型有風險,需要程序員手動干預。本節只介紹向上轉型,向下轉型將在后續章節介紹。
向上轉型和向下轉型是面向對象編程的一種通用概念,它們也存在于 Java、C# 等編程語言中。
將派生類對象賦值給基類對象
下面的例子演示了如何將派生類對象賦值給基類對象:
#include <iostream>using namespace std;//基類class A{public:A(int a);int m_a; public:void display();};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 a1,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;} Class A:m_a=10 Class B:m_a=66, m_b99 --------------- Class A:m_a=66 Class B:m_a=66, m_b99本例中 A 是基類, B 是派生類,a、b 分別是它們的對象,由于派生類 B 包含了從基類 A 繼承來的成員,因此可以將派生類對象 b 賦值給基類對象 a。通過運行結果也可以發現,賦值后 a 所包含的成員變量的值已經發生了變化。
賦值的本質是將現有的數據寫入已分配好的內存中,對象的內存只包含了成員變量,所以對象之間的賦值是成員變量的賦值,成員函數不存在賦值問題。
運行結果也有力地證明了這一點,雖然有a=b;這樣的賦值過程,但是 a.display() 始終調用的都是 A 類的 display() 函數。換句話說,對象之間的賦值不會影響成員函數,也不會影響 this 指針。
將派生類對象賦值給基類對象時,會舍棄派生類新增的成員,也就是“大材小用”,如下圖所示:
可以發現,即使將派生類對象賦值給基類對象,基類對象也不會包含派生類的成員,所以依然不同通過基類對象來訪問派生類的成員。對于上面的例子,a.m_a 是正確的,但 a.m_b 就是錯誤的,因為 a 不包含成員 m_b。
這種轉換關系是不可逆的,只能用派生類對象給基類對象賦值,而不能用基類對象給派生類對象賦值。理由很簡單,基類不包含派生類的成員變量,無法對派生類的成員變量賦值。同理,同一基類的不同派生類對象之間也不能賦值。
要理解這個問題,還得從賦值的本質入手。賦值實際上是向內存填充數據,當數據較多時很好處理,舍棄即可;本例中將 b 賦值給 a 時(執行a=b;語句),成員 m_b 是多余的,會被直接丟掉,所以不會發生賦值錯誤。但當數據較少時,問題就很棘手,編譯器不知道如何填充剩下的內存;如果本例中有b= a;這樣的語句,編譯器就不知道該如何給變量 m_b 賦值,所以會發生錯誤。
總結
以上是生活随笔為你收集整理的C++将派生类赋值给基类(向上转型)(一)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: C++虚继承下的内存模型(二)
- 下一篇: 将派生类指针赋值给基类的指针