中文字幕av专区_日韩电影在线播放_精品国产精品久久一区免费式_av在线免费观看网站

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

C++基礎入門篇之強制轉換講解

發布時間:2021-03-05 16:32:11 來源:億速云 閱讀:340 作者:TREX 欄目:開發技術

本篇內容主要講解“C++基礎入門篇之強制轉換講解”,感興趣的朋友不妨來看看。本文介紹的方法操作簡單快捷,實用性強。下面就讓小編來帶大家學習“C++基礎入門篇之強制轉換講解”吧!

引言

假設有基類 A,包含了虛函數 func1,以及有派生類 B,繼承于類 A,派生類 B 中實現了函數 func1。此時可以用 A 類型的指針指向 B 類型的對象,并用 A 類型的指針調用 B 類型對象中的函數 func1。這時,就形成了多態。包含虛函數的類 A,我們也稱為多態類。

由于派生類 B 完整包含了 基類 A 的所有定義,將 B 類型的指針轉換為 A 類型的指針總是安全的。

而將 A 類型的指針強制轉換為 B 類型的指針時,如果 A 類型指針指向的對象確實為 B 類型的對象,那么轉換也是安全的。此時,該 B 類型對象被稱為完整對象(complete object)。

強制轉換有哪些類型?

C++ 包含了以下幾種強制轉換運算符,這些運算符用于消除老式 C 語言轉換中的存在的歧義和隱患:

  • dynamic_cast

  • static_cast

  • const_cast

  • reinterpret_cast

  • safe_cast

本文會著重介紹如何使用 dynamic_cast 和 static_cast。

提醒:

除非必須,不要使用 const_cast 和 reinterpret_cast,因為它們存在一些老式 C 語言轉換中的隱患。

dynamic_cast 運算符

語法:

 dynamic_cast <type-id> (expression)

type-id 必須是一個指針或者引用,指向/引用已定義的類類型或者 void。如果type-id 是指針,則 expression 必須也為指針類型,如果 type-id 是引用,expression 必須為左值類型。

如果 type-id 是 void*,那么在運行時將檢測 expression 的實際類型。其結果返回 expression 指向的完整對象。

如非需要,現代 C++ 中應該避免使用 void 指針,因為容易出錯。

下面看些示例,了解 dynamic_cast 的使用方式。

示例1:

class Root { };
class Base : public Root { };
class Derived : public Base { };

void f(Derived* pd) {
 Base* pb = dynamic_cast<Base*>(pd); // ok: Base is a direct base class
         // pb points to Base subobject of pd
 Root* pr = dynamic_cast<Root*>(pd); // ok: Root is an indirect base class
         // pr points to Root subobject of pd
}

示例1 中提到了子對象(subobject)的概念,注意與子類型進行區分:

  • Root 類型包含子類型 Base,Base 類型包含子類型 Derived。

  • Derived 對象包含了 Base 類型的子對象,Base 類型的子對象又包含了 Root 類型的子對象。

再聯系下前面說的:派生類完整包含了基類的所有定義。

示例2:

class B {virtual void f();};
class D : public B {virtual void f();};

void f() {
 B* pb = new D; // unclear but ok
 B* pb2 = new B;

 D* pd = dynamic_cast<D*>(pb); // ok: pb actually points to a D
 D* pd2 = dynamic_cast<D*>(pb2); // pb2 was nullptr.
}

示例2 中 通過 dynamic_cast 轉換為 pd2 時,不會報錯,返回 nullptr。但如果同樣地情況轉換的對象是引用類型,那么運行時會拋出 std::bad_cast 異常。如果 pb2 指向/引用的對象無效,同樣也會拋出異常。

示例3:

#include <stdio.h>
#include <iostream>

struct A {
 virtual void test() {
  printf_s("in A\n");
 }
};

struct B : A {
 virtual void test() {
  printf_s("in B\n");
 }

 void test2() {
  printf_s("test2 in B\n");
 }
};

struct C : B {
 virtual void test() {
  printf_s("in C\n");
 }

 void test2() {
  printf_s("test2 in C\n");
 }
};

void Globaltest(A& a) {
 try {
  C &c = dynamic_cast<C&>(a);
  printf_s("in GlobalTest\n");
 }
 catch(std::bad_cast) {
  printf_s("Can't cast to C\n");
 }
}

int main() {
 A *pa = new C;
 A *pa2 = new B;

 pa->test();

 B * pb = dynamic_cast<B *>(pa);
 if (pb)
  pb->test2();

 C * pc = dynamic_cast<C *>(pa2);
 if (pc)
  pc->test2();

 C ConStack;
 Globaltest(ConStack);

 // will fail because B knows nothing about C
 B BonStack;
 Globaltest(BonStack);
}
Output:

in C
test2 in B
in GlobalTest
Can't cast to C

static_cast 運算符

語法:

static_cast <type-id> (expression)

static_cast 通常用于數值類型轉換,例如枚舉和整型,整型和浮點類型的轉換。

在標準 C++ 中,static_cast 轉換沒有運行時檢測來保證安全性。在 C++/CX 中,則包含了編譯和運行時檢測。

static_cast 運算符能夠用于將基類指針轉換為派生類指針,但這樣的轉換不總是安全的。

下面還是通過示例進行講解。

示例1:

class B {};
class D : public B {};

void f(B* pb, D* pd) {
 D* pd2 = static_cast<D*>(pb); // Not safe, D can have fields
         // and methods that are not in B.

 B* pb2 = static_cast<B*>(pd); // Safe conversion, D always
         // contains all of B.
}

示例1 中 pd2 不為空,當用指針 pd2 調用 B 類型對象不存在的方法或者成員時可能會發生運行時錯誤(比如調用虛函數)或者返回非預期的值。

示例2:

typedef unsigned char BYTE;

void f() {
 char ch;
 int i = 65;
 float f = 2.5;
 double dbl;

 ch = static_cast<char>(i); // int to char
 dbl = static_cast<double>(f); // float to double
 i = static_cast<BYTE>(ch);
}

示例2 中 static_cast 運算符顯示地將內置類型進行轉換。

關于 static_cast 運算符,還有以下幾種使用情況:

  • static_cast 能夠顯式的將整型轉換為枚舉類型。如果整型值不在枚舉值范圍內,那么返回的枚舉值是未定義的。

  • static_cast 能將任何 expression 顯式地轉換為 void 類型。

  • static_cast 操作符不會去除 const,volatile,__unaligned 屬性。

區分幾種強制轉換的使用場景

dynamic_cast 主要用于多態類型的強制轉換,而 static_cast 主要用于非多態類型的強制轉換。

static_cast 轉換不像 dynamic_cast 那樣安全。因為 static_cast 沒有運行時檢測。通過 dynamic_cast 進行轉換時,一旦存在歧義,就會導致失敗,然而 static_cast 會像沒有錯誤發生一樣返回結果。盡管 dynamic_cast 更加安全,但 dynamic_cast 僅適用于指針和引用,并且運行時檢測是需要消耗性能的。

示例:

class B {
public:
 virtual void Test(){}
};
class D : public B {};

void f(B* pb) {
 D* pd1 = dynamic_cast<D*>(pb);
 D* pd2 = static_cast<D*>(pb);
}

如果 pb 實際指向類型 D 或者 pd == 0,那么 pd1 和 pd2 將獲得相同的值。

如果 pb 實際指向類型 B,那么 dynamic_cast 會返回 0。但是 static_cast 依賴于 expression 認定 pb 指向 D 類型對象,于是簡單的返回 D 類型的指針。

結果就是,static_cast 轉換會繼續執行,但其返回結果是未定義的。這就需要調用者去進一步驗證轉換結果是有效的。

總結

到此,相信大家對“C++基礎入門篇之強制轉換講解”有了更深的了解,不妨來實際操作一番吧!這里是億速云網站,更多相關內容可以進入相關頻道進行查詢,關注我們,繼續學習!

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

兴城市| 颍上县| 丰都县| 佛坪县| 九寨沟县| 巴马| 景洪市| 林口县| 黄浦区| 西青区| 垣曲县| 南澳县| 定边县| 临泽县| 平顺县| 辉南县| 柘城县| 砚山县| 诸暨市| 潞西市| 中江县| 新密市| 哈巴河县| 江西省| 萨迦县| 抚远县| 兰州市| 桐城市| 读书| 平阳县| 治多县| 霞浦县| 天津市| 永定县| 阿克苏市| 万年县| 娱乐| 大石桥市| 田东县| 平凉市| 读书|