寫在move之前 關於型別轉換

2021-08-31 23:29:08 字數 4874 閱讀 6385

回顧一下primer c++裡面,有關轉換的內容

首先是型別轉換,型別轉換裡面就包含了隱式轉換和顯示轉換

先回顧一下基本型別隱式轉換的原則:

看一下primer的例子

int ival = 3.541 + 3
右邊:double+int,int會轉換為double(隱式轉換一次)執行加法運算,這裡體現了以上原則,在賦值的時候,double 賦給int(隱式轉換第二次)

這主要是算術轉換,裡面還包含了一些其它內容,包括有符號和無符號做算術運算時候的轉換,bool轉換等,其它的還有一些指標的轉換,常量與非常量之間的轉換,隱式轉換只支援非常量轉換成常量,否則,呵呵,編譯器會讓你難受的

而decltype則只推斷表示式最終結果的變數型別

舉乙個簡單的例子:

int i=1;

auto a=i;

decltype(i) x=5;

接下來就是顯式型別轉換

老式的顯示轉換格式是這樣的:

type(expr);

(type)expr;

你是不是寫過float f=5.3; int i=(int)f;這類**,哈哈哈,我也是,現在我盡量避免這類**了,因為一旦表示式變複雜,你要是出錯了,可能就麻煩了,乙個bug找一天真的很難

看看c++ 11支援顯示轉換的形式和關鍵字

cast-name(expression);
cast_name即為關鍵字:static_cast、dynamic_cast、const_cast、reinterpret_cast

執行資料型別的強制轉換,在隱式轉換中,如果存在精度損失,編譯器會給出warning,但是static_cast強制轉換則會避免這個warning,這樣聽起來好像沒什麼用,可能這個warning資訊很關鍵呢

它的另乙個用法是把void*型別指標轉換成目標型別的指標,但是必須保證他們所指的型別相同,也就是在void*之前的型別和cast type相同

另外它在進行上行轉換(把派生類的指標或引用轉換為基類表示)是安全的,而下行轉換是不安全的,這裡提到的類型別指標的轉換,一定是有一定聯絡的類,不相關的類不可以,但是編譯器自帶的基本型別似乎都可以,

需要注意的是帶有一些const的關鍵字是不能轉換的,好像還有一些其它關鍵字也不可以。

聽起來這些功能都沒什麼大用,因為warning是有用的,知道void*指標變化前後的型別,需要void*幹嘛,但是不可忽略的就是顯式轉換可以避免隱式轉換帶來的一些錯誤,這真的很關鍵,有一些隱藏的bug就存在隱式轉換中,讓你無法查詢,顯式轉換責任則讓你一眼就知道**在幹什麼,有沒有幹出格的事

看乙個static_cast的例項:

test_convert.h

#include "stdafx.h"

class cconverta

public:

int m_a;

};class cconvertb:public cconverta

;class cconvertc

;void show_convert();

test_convert.cpp

void show_convert()

我對於const_cast的認識,很膚淺,簡單的認為它就是為指標工作的,就是去掉指向常數物件指標的常量性,如何理解呢,先看看指向常量的指標和指標常量的區別

看看primer裡面的例子

const double pi=3.14;//double常量

double *ptr=π//想用乙個指標指向乙個常量物件,這是不被允許的,因為要想存放常量的指標,必須使用指//向常量的位址

const double *cptr=π//這是指向常量的指標的寫法

*cptr=42;//這是不被允許的,指向常量的指標,就是指的不用指標去改變變數的值

double dval=3.14;

cptr=&dval;//這是允許的,指向常量的指標可以指向普通量

看明白了吧,指向常量的指標核心是不能用指標去改變所指物件的值

再看看常指標

int errnumb=0;

int *const curerr=&errnumb;//這是常量指標的寫法,注意長指標一旦完成初始化,即指向明確了後,就不允//許改變了

const double pi=3.14;

const double *const pip = π//要區分是常量指標還是指向常量的指標,主要看const的位置,如果//const緊靠變數名,就表示變數是const,如果const緊靠變數type,就表示所指物件是const,這裡就表示

//乙個指向常量的常指標指向了乙個常量,有點繞,但你仔細讀,說的沒錯

總結一下,就是對於常變數,只能用指向常量的指標指向它,但是指向常量的指標還可以指向普通變數,需要注意的是,對於指向常量的指標就是不允許它改變所指物件的值,而常指標沒什麼特別的,就是一旦指向完成,就不允許改變指向了

在primer定義了頂層const(指標本身是乙個常量)和底層const(所指物件是乙個const),就是乙個能不能改變指向的區分,不要想的太複雜,而底層const所指物件是不能改變的,需要注意的是不能用乙個普通的指標去拷貝這個指標,你知道的,這會讓底層const失效,就是物件可能被這個拷貝的指標改變,當然,編譯器也不會讓你幹這種事的,但是你又可以用另乙個指向常量的指標去copy另乙個指向常量的指標,這好像沒什麼用,但也對物件沒什麼損害。

總結一下,就是對於指向常量的指標是可以被另乙個指向常量的指標copy,但是不能普通指標copy,不能破壞底層const,另外如果乙個普通指標也可以給常指標賦值,這很棒,這裡有個我總結過的原則,就是後面出現的內容,不應該去破壞前面建立的機制與準則,就是前面是const,不想被改變,你後面出現的內容肯定要遵守的。

下面我們回到const_cast,這就很好理解了,我們看個例子:

const double pi=3.14;

double dvt=3.14;

const double* p_c=π//指向常量的指標指向了乙個常量

const double* p_n=&dvt;//指向常量的指標指向了乙個普通變數

double* p_1=const_cast(p_c);//這是允許的,但是注意,p_c指向常量,所以,p不能用,雖然通//過編譯

double* p_2=const_cast(p_n);//這也是允許的,但是注意,p_n指向乙個普通變數,所以,你可//以用p_2去做一些修改,比如做了*p=3.15,這是不會報錯的,

注意到了吧,這就是核心,const_cast能做的就是把乙個指向普通變數的指標常量轉換為乙個普通指標,然後對被指向物件做一些改變,還是那句話,底層const不容破壞,誰讓你後來呢。這是我的理解,當然還有些高階的用法,我還沒理解透

我個人認為reinterpret_cast是完全沒必要用的,就像關鍵字自己傳達的意思一樣,重新解釋,你看一下吧,它幹了什麼

int *ip;

char *pc=reinterpret_cast(ip);

它把乙個int型別的指標賦值到char型別指標,這算什麼,你用的時候它得是char型別指標,但是你還得記住它實際是int位址,這真的很危險,你記不住,也用不出什麼好效果,像 我一樣,摒棄它是最好的方法;

dynamic_cast放到最後來講,因為這個真的要複雜一些,我不得不翻一些別人的部落格和書。

dynamic_cast(e);

dynamic_cast(e);

dynamic_cast(e);

這是primer裡面提到的表現形式,需要注意的是有以下幾點:

type必須是乙個類型別,即不能用於基本資料型別的強制轉換,並且通常情況下該型別應該含有虛函式

e的型別必須是目標型別的公有派生類、公有基類、同型別(就是型別必須是公有繼承的關係)

dynamic_cast是在執行時處理的,執行時進行型別檢查,如果轉換目標型別與被轉換指標所指向是相同的,就會成功,否則會失敗

這裡面有幾個問題,乙個是虛函式,乙個是向下轉換檢查,怎麼說呢,我好像已經寫的很長了,還要寫個虛函式的作用麼,我們直接看例子吧

test_convert.h

#include "stdafx.h"

#include "iostream"

class cconverta

public:

virtual void f()

public:

int m_a;

};class cconvertb:public cconverta

public:

int m_b;

int m_c;

};class cconvertc

;void show_convert_static_cast();

void show_convert_const_cast();

void show_convert_dynamic_cast();

test_convert.cpp

#include "stdafx.h"

#include "test_convert.h"

#include "iostream"

void show_convert_static_cast()

void show_convert_const_cast()

void show_convert_dynamic_cast()

else

b = dynamic_cast(a2);//注定會失敗的

if (b == null)

c = dynamic_cast(a1);//注定會失敗的

if (b == null)

return;

}

ending

關於型別轉換

關於型別轉換,這裡只列舉類之間的型別轉換 其難點有在基類和派生類之間的資料型別轉換 在物件導向程式設計中,派生類實際上是基類的例項,但加上了一些額外資訊.在基類上所有的函式和字段也都在派生類上定義了,所以派生類可以隱式轉換為基類,看下面的例子 equals eq1 new equalss 基類和派生...

關於型別轉換

一 號 在不同的情況下作用是不同的 1.字串 字串 字串 2.字串 數字 字串 3.數字 數字 數字 4.作為正號時,可以將字串轉化成數字 eg typeof 1 2 型別是number 結果是3 二 號 無論什麼情況下都是數字相減,進行隱式轉化成數字 三 與 的區別 1.可以將字串轉化成數字 2....

關於格式型別轉換

c 中提供 4種顯式型別轉換。今天實驗了其中的 static cast const cast 與 reinterpret cast。static cast 轉換用於比較安全的轉換或者意義清晰的轉換。同時可以用於顯式地說明編譯器自動的隱式型別轉換。static cast.cpp includeusin...