【C++grammar】動態類型轉換、typeid與RTTI

目錄

  • 動態類型轉換
    • 1、為何需要動態類型轉換
    • 2、dynamic_cast<>();運算符
    • 3、向上轉換和向下轉換( Upcasting and Downcasting)
    • 4、 基類對象和派生類對象的互操作
    • 5、Upcasting/Downcasting與繼承鏈上不同類的對象之間的賦值有什么關系和區別?
  • typeid 運行時查詢類型的信息
  • RTTI與typeid 的關系

動態類型轉換

1、為何需要動態類型轉換

在這里插入圖片描述
定義一個函數:

void printObject(Shape& shape)
//shape是派生類對象的引用
{cout<<"The area is"<<shape.getArea()<<endl;//如果是circle,就輸出半徑//如果是rectangle,就輸出寬和高
}

如果這個shape指向的是一個circle類型的對象,我們想顯示它的半徑,該怎么辦?

2、dynamic_cast<>();運算符

dynamic_cast<>();
沿著繼承層次向上、向下以及側向轉換到類的指針和引用。
轉指針:失敗返回nullptr
轉引用:失敗拋異常

步驟:
1、先將shape類對象用dynamic_cast轉換為派生類對象
2、然后調用派生類中獨有的函數
如下所示:

void printObject(Shape& shape)
//shape是派生類對象的引用
{cout<<"The area is"<<shape.getArea()<<endl;//先獲取基類指針Shape *p = &shape;//將基類指針轉換為派生類指針Circle *c = dynamic_cast<Circle*>(p);//Circle& c = dynamic_cast<Circle&>(shape);//引用轉換失敗則拋出一個異常	std::bad_cast//如果shape是Circle對象,那么會成功,如果不是則不會成功if(c != nullptr)	//轉換失敗則指針為空{cout<<"The radius is"<<c->getRadius()<<endl;}
}

3、向上轉換和向下轉換( Upcasting and Downcasting)

upcasting:將派生類類型指針賦值給基類類型指針。
downcasting : 將基類類型指針賦值給派生類類型指針。

圖1
圖2
**1、上轉可不使用dynamic_cast而隱式轉換**
Shape* s = nullptr;Circle *c = new Circle(2);s = c; //OK,隱式上轉

2、下轉必須顯式執行

Shape* s = new Circle(1);Circle *c = nullptr;c = dynamic_cast <Circle*> (s); //顯式下轉

什么是側向轉換?
動態類型轉換可以上轉也可以下轉。那么什么是側向轉換?
比如說circle和rectangle都是繼承的shape,他們同級之間相互轉換就是側向轉換。

4、 基類對象和派生類對象的互操作

之前的向上和向下轉換都是以指針為例,現在不是指針了,而是對象。
首先看對象的內存布局:
首先定義一個父類和一個子類對象:

Shape S;
Circle C;

對象成員一覽:
1、可以看出來派生類對象比基類對象多出來一點東西。
2、派生類里面包含了一個基類對象的數據
在這里插入圖片描述
同時給出兩個規則:

1、可將派生類對象截斷,只使用繼承來的信息
2、但不能將基類對象加長,無中生有變出派生類對象

了解到上面的知識之后,判斷下面四個對錯:

1、S = C;
2、C = S;
3、Shape &rS = C;
4、Circle &rC = S;

顯然是13對(將派生類對象截斷,只使用繼承來的信息),24錯(不能使基類對象加長,無中生有變出派生類對象)

5、Upcasting/Downcasting與繼承鏈上不同類的對象之間的賦值有什么關系和區別?

向上向下轉換只要是在同一個繼承鏈上都是可以成立的。
而不同對象之間的賦值,只允許從下往上賦值,傳遞被繼承的信息。

typeid 運行時查詢類型的信息

typeid用于獲取對象所屬的類的信息:

(1) typeid returns a reference to an object of class type_info. (typeid運算符返回一個type_info對象的引用)
(2) typeid(AType).name() 返回實現定義的,含有類型名稱的C風格字符串(char *)

#include <typeinfo>  //使用typeid,需要包含此頭文件 
#include <iostream>  
class A {};
A a{};
// ……
int main()
{auto& t1 = typeid(a);if (typeid(A) == t1) {std::cout << "a has type "<< t1.name() << std::endl;}
}

結果:
在這里插入圖片描述

RTTI與typeid 的關系

RTTI(Run-Time Type Identification),通過運行時類型信息程序能夠使用基類的指針或引用來檢查這些指針或引用所指的對象的實際派生類型。

RTTI提供了以下兩個非常有用的操作符:

(1)typeid操作符,返回指針和引用所指的實際類型。
(2)dynamic_cast操作符,將基類類型的指針或引用安全地轉換為派生類型的指針或引用。

面向對象的編程語言,像C++,Java,delphi都提供了對RTTI的支持。 本文將簡略介紹 RTTI 的一些背景知識、描述 RTTI 的概念,并通過具體例子和代碼介紹什么時候使用以及如何使用 RTTI;本文還將詳細描述兩個重要的 RTTI 運算符的使用方法,它們是 typeid 和dynamic_cast。
其實,RTTI 在C++中并不是什么新的東西,它早在十多年以前就已經出現了。但是大多數開發人員,包括許多高層次的C++程序員對它并不怎么熟悉,更不用說使用 RTTI 來設計和編寫應用程序了。
一些面向對象專家在傳播自己的設計理念時,大多都主張在設計和開發中明智地使用虛擬成員函數,而不用 RTTI 機制。但是,在很多情況下,虛擬函數無法克服本身的局限。每每涉及到處理異類容器和根基類層次(如 MFC)時,不可避免要對對象類型進行動態判斷,也就是動態類型的偵測。如何確定對象的動態類型呢?答案是使用內建的 RTTI 中的運算符:typeid 和 dynamic_cast。
在C++中存在虛函數,也就存在了多態性,對于多態性的對象,在程序編譯時可能會出現無法確定對象的類型的情況。當類中含有虛函數時,其基類的指針就可以指向任何派生類的對象,這時就有可能不知道基類指針到底指向的是哪個對象的情況,類型的確定要在運行時利用運行時類型標識做出。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/377696.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/377696.shtml
英文地址,請注明出處:http://en.pswp.cn/news/377696.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

nginx資源定向 css js路徑問題

今天玩玩項目&#xff0c;學學nginx發現還不錯&#xff0c;速度還可以&#xff0c;但是CSS JS確無法使用&#xff0c;原來Iginx配置時需要對不同類型的文件配置規則&#xff0c;真是很郁悶&#xff0c;不過想想也還是很有道理。閑暇之際&#xff0c;把配置貼上來。#user nobody…

五、庫存查詢功能的完善

一、數據庫的建立 由于查詢功能和之前的 入庫管理功能 所用的數據庫都一樣&#xff0c;這里仍使用yy_textile表 在fiber_yy數據庫下創建yy_textile表 初始數據庫信息 二、頁面的完善 登錄注冊頁面我就不演示了&#xff0c;前幾篇博文也都有介紹 query查詢頁面 main_page…

整合ajaxmin 和 less 到VS.net

我用的前端框架是bootstrap_extra, twitter團隊做的&#xff0c;這個是他的一個擴展&#xff0c;首先從上面下載一個。至于ajaxmin&#xff0c;請參考這里1) 從bootstrap_extra的解壓包中&#xff0c;復制build目錄下三個文件到項目中去&#xff0c;這三個文件分別是BatchSubsi…

轉:只能選擇GridView中的一個CheckBox(單選CheckBox)

方法1&#xff1a; protected void GridView2_RowDataBound(object sender, GridViewRowEventArgs e){CheckBox cbx e.Row.FindControl("cbID") as CheckBox;try{//綁定選中CheckBox 客戶端IDcbx.Attributes.Add("onclick", "Change(" cbx.Cli…

六、出庫管理功能的實現

一、數據庫的建立 這里仍使用yy_textile表 在fiber_yy數據庫下創建yy_textile表 初始數據庫信息 二、頁面的完善 登錄注冊頁面我就不演示了&#xff0c;前幾篇博文也都有介紹 shipment出庫管理頁面 main_page頁面進行功能完善 三、代碼實現 shipment出庫管理頁面 u…

數學建模:層次分析法實例以及代碼

博主聯系方式&#xff1a; QQ:1540984562 QQ交流群&#xff1a;892023501 群里會有往屆的smarters和電賽選手&#xff0c;群里也會不時分享一些有用的資料&#xff0c;有問題可以在群里多問問。 目錄層次分析法的思想層次分析法步驟具體案例(市政工程項目建設決策)1.問題提出2.…

c 僵尸進程_演示僵尸進程的C程序

c 僵尸進程僵尸進程 (Zombie process) A process which has finished its execution but still has an entry in the process table to report to its parent process is known as a zombie process. 一個已經完成執行但仍在進程表中具有要報告給其父進程的條目的進程稱為僵尸進…

探秘IntelliJ IDEA 13測試版新功能——調試器顯示本地變量

IntelliJ IDEA在業界被公認為最好的Java開發平臺之一&#xff0c;JetBrains公司將在12月正式發布IntelliJ IDEA 13版本。 現在&#xff0c;小編將和大家一起探秘密IntelliJ IDEA 13測試版本新功能——調試器顯示本地變量。這個功能非常強大&#xff0c;調試器可以顯示變量&…

C# Windows Form下的控件的Validator(數據驗證)

由于偶爾的一個想法&#xff0c;謀生了一個做一個windows form下的Validator控件&#xff0c;或者直接說類吧&#xff01; 因為webform下的Validator控件太好用了。哈哈&#xff0c;直接看代碼&#xff01; 下面這個類&#xff0c;主要是一個簡單的驗證類&#xff0c;不過只是起…

七、流水查詢---記錄用戶登錄信息

一、數據庫的建立 在fiber_yy數據庫下創建yy_user_record表 可以先手動填入幾條數據信息 初始數據庫信息 username為用戶賬號 sex為用戶注冊所填寫的性別 phone為用戶手機號 time為用戶登錄該系統的時間 二、頁面的設計 登錄注冊頁面我就不演示了&#xff0c;前幾篇博文…

leetcode 455. 分發餅干 思考分析

目錄題目自己的思路以及AC代碼參考思路題目 假設你是一位很棒的家長&#xff0c;想要給你的孩子們一些小餅干。但是&#xff0c;每個孩子最多只能給一塊餅干。 對每個孩子 i&#xff0c;都有一個胃口值 g[i]&#xff0c;這是能讓孩子們滿足胃口的餅干的最小尺寸&#xff1b;并…

c++ cdi+示例_C ++'not'關鍵字和示例

c cdi示例"not" is an inbuilt keyword that has been around since at least C98. It is an alternative to ! (Logical NOT) operator and it mostly uses with the conditions. “ not”是一個內置關鍵字&#xff0c;至少從C 98起就存在。 它是替代&#xff01; …

【second】Flatten Binary Tree to Linked List

遞歸 void flatten(TreeNode *root) {// Note: The Solution object is instantiated only once and is reused by each test case.flat(root);}TreeNode* flat(TreeNode* root){if(!root)return NULL;TreeNode* left_tail flat(root->left);TreeNode* right_tail flat(ro…

八、流水查詢---記錄紡織品出庫信息

一、數據庫的建立 在fiber_yy數據庫下創建yy_textile_record表 可以先手動填入幾條數據信息 初始數據庫信息 第一條數據的username是空格不是null number為織物的品號(唯一的) stock為出貨量 username為哪個賬號 time為出貨時間 二、頁面的完善 登錄注冊頁面我就不演示…

應用程序欄【WP7學習札記之九】

本節是WP7學習札記的第九篇&#xff0c;講的是系統托盤和應用程序欄&#xff0c;具體內容是系統托盤和應用程序欄的介紹&#xff0c;如何分別使用C#、xaml以及Expression Blend生成應用程序欄&#xff0c;應用程序欄的透明度以及對屏幕方向改變的支持。摘要如下&#xff1a; 系…

橢圓曲線密碼學導論pdf_橢圓曲線密碼學

橢圓曲線密碼學導論pdf歷史 (History) The use of elliptic curves in cryptography was advised independently by Neal Koblitz and Victor S. Miller in 1985. Elliptic curve cryptography algorithms entered large use from 2004 to 2005. 1985年&#xff0c; Neal Kobli…

leetcode 第 216 場周賽 整理

目錄1662. 檢查兩個字符串數組是否相等題目自己代碼5606. 具有給定數值的最小字符串題目自己代碼貪心算法1664. 生成平衡數組的方案數題目自己代碼動態規劃優化1665. 完成所有任務的最少初始能量題目思路1662. 檢查兩個字符串數組是否相等 題目 給你兩個字符串數組 word1 和 …

九、忘記密碼功能的實現

一、頁面設計 login頁面&#xff0c;和第二篇博文(用戶登錄和注冊)頁面基本一樣&#xff0c;只不過多了一個按鈕 其中忘記密碼&#xff1f;點我找回 為button3 retrieve_password頁面 change_password頁面 頁面如下&#xff1a; 二、數據庫 因為是忘記密碼&#xff0c;…

Android中對手機文件進行讀寫

參考張澤華視頻 &#xff08;一&#xff09;讀寫手機內存卡中的文件 對手機中的文件進行讀寫操作&#xff0c;或者新增一個文件時&#xff0c;可直接使用openFileOutput / openFileInput 得到文件的輸出、輸入流。 FileOutputStream fos this.openFileOutput("private.…

聯軸器選型_聯軸器| 軟件工程

聯軸器選型耦合 (Coupling) In general terms, the term coupling is defined as a thing that joins together two objects. If we talk about software development, then the term coupling is related to the connection between two modules, i.e. how tight interaction …