C 向上轉型

2021-07-31 17:03:51 字數 1894 閱讀 2744

類其實也是一種資料型別,也可以發生資料型別轉換,不過這種轉換只有在基類和派生類之間才有意義,並且只能將派生類賦值給基類,包括將派生類物件賦值給基類物件、將派生類指標賦值給基類指標、將派生類引用賦值給基類引用,這在 c++ 中稱為向上轉型(upcasting)。相應地,將基類賦值給派生類稱為向下轉型(downcasting)。

向上轉型非常安全,可以由編譯器自動完成;

向下轉型有風險,需要程式設計師手動干預(有時編譯器認為只是錯誤)

賦值的本質是將現有的資料寫入已分配好的記憶體中,物件的記憶體只包含了成員變數,所以物件之間的賦值是成員變數的賦值,成員函式不存在賦值問題。

將派生類物件賦值給基類物件時,會捨棄派生類新增的成員,所以不存在安全問題。

即使將派生類物件賦值給基類物件,基類物件也不會包含派生類的成員,所以依然不能通過基類物件來訪問派生類的成員。

這種轉換關係是不可逆的,只能用派生類物件給基類物件賦值,而不能用基類物件給派生類物件賦值。理由很簡單,

基類不包含派生類的成員變數,無法對派生類的成員變數賦值。同理,同一基類的不同派生類物件之間也不能賦值。

要理解這個問題,還得從賦值的本質入手。賦值實際上是向記憶體填充資料,當資料較多時很好處理,捨棄即可,所以不會發生賦值錯誤。但當資料較少時,問題就很棘手,編譯器不知道如何填充剩下的記憶體;如果本例中有b= a;這樣的語句,編譯器就不知道該如何給變數 m_b 賦值,所以會發生錯誤。

派生類指標賦值給基類指標

除了可以將派生類物件賦值給基類物件(物件變數之間的賦值),還可以將派生類指標賦值給基類指標(物件指標之間的賦值)

下面看一段示例**:

#include

using namespace std;

class a;

a::a(int a): m_a(a)

void a::display()

//中間派生類b

class b: public a;

b::b(int a, int b): a(a), m_b(b)

void b::display()

//基類c

class c;

c::c(int c): m_c(c)

void c::display()

//最終派生類d

class d: public b, public c;

d::d(int a, int b, int c, int d): b(a, b), c(c), m_d(d)

void d::display()

int main()

解 釋:

我們將派生類指標 pd 賦值給了基類指標 pa,從執行結果可以看出,呼叫 display() 函式時雖然使用了派生類的成員變數,但是 display() 函式本身卻是基類的。也就是說,將派生類指標賦值給基類指標時,通過基類指標只能使用派生類的成員變數,但不能使用派生類的成員函式,這看起來有點不倫不類,究竟是為什麼呢?  

pa 本來是基類 a 的指標,現在指向了派生類 d 的物件,這使得隱式指標 this 發生了變化,也指向了 d 類的物件,所以最終在 display() 內部使用的是 d 類物件的成員變數,相信這一點不難理解。

編譯器雖然通過指標的指向來訪問成員變數,但是卻不通過指標的指向來訪問成員函式:編譯器通過指標的型別來訪問成員函式。對於 pa,它的型別是 a,不管它指向哪個物件,使用的都是 a 類的成員函式。 

概括起來說就是:編譯器通過指標來訪問成員變數,指標指向哪個物件就使用哪個物件的資料;編譯器通過指標的型別來訪問成員函式,指標屬於哪個類的型別就使用哪個類的函式。

本例中我們將最終派生類的指標 pd 分別賦值給了基類指標 pa、pb、pc,按理說它們的值應該相等,都指向同一塊記憶體,但是執行結果卻有力地反駁了這種推論,只有 pa、pb、pd 三個指標的值相等,pc 的值比它們都大。也就是說,執行pc = pd;語句後,pc 和 pd 的值並不相等。 



C 向上轉型

在學習c 的過程中,一些基礎知識比如資料型別 控制結構 陣列等都與之前接觸的語言大同小異,還能夠理解,但是向上轉型這個概念還是第一次遇到。學習了一下後大致理解如下 向上轉型就是將子類轉型成父類,物件可以作為它本身的型別使用。先來看一段 public class animal public class...

C 向上轉型

在 c c 中經常會發生資料型別的轉換,例如將 int 型別的資料賦值給 float 型別的變數時,編譯器會先把 int 型別的資料轉換為 float 型別再賦值 反過來,float 型別的資料在經過型別轉換後也可以賦值給 int 型別的變數。資料型別轉換的前提是,編譯器知道如何對資料進行取捨。例如...

C 向上轉型

在 c 中經常會發生資料型別的轉換,例如將 int 型別的資料賦值給 float 型別的變數時,編譯器會先把 int 型別的資料轉換為 float 型別再賦值 反過來,float 型別的資料在經過型別轉換後也可以賦值給 int 型別的變數。資料型別轉換的前提是,編譯器知道如何對資料進行取捨。例如 i...