亚洲在线久爱草,狠狠天天香蕉网,天天搞日日干久草,伊人亚洲日本欧美

為了賬號安全,請及時綁定郵箱和手機立即綁定
已解決430363個問題,去搜搜看,總會有你想問的

求指教,是關于C++,const_cast的用法的問題,麻煩看一下哦!

求指教,是關于C++,const_cast的用法的問題,麻煩看一下哦!

慕森卡 2021-06-23 18:15:14
const int a=789 ; const_cast<int>(a)=987;================================================1>------ 已啟動生成: 項目: 2, 配置: Debug Win32 ------1>正在編譯...1>Main.cpp1>c:\users\administrator\desktop\2\2\2\main.cpp(9) : error C2440: “const_cast”: 無法從“const int”轉換為“int”1>        轉換是有效的標準轉換,可以隱式執行或通過使用 static_cast、C 樣式轉換或函數樣式轉換執行1>生成日志保存在“file://c:\Users\Administrator\Desktop\2\2\2\Debug\BuildLog.htm”1>2 - 1 個錯誤,0 個警告========== 生成: 成功 0 個,失敗 1 個,最新 0 個,跳過 0 個 ==========
查看完整描述

2 回答

?
慕田峪9158850

TA貢獻1794條經驗 獲得超8個贊

C++標準轉換運算符const_cast
C++相比于C是一門面向對象的語言,面向對象最大的特點之一就是具有“多態性(Polymorphism)”。
C++提供了四個轉換運算符:
const_cast <new_type> (expression)
static_cast <new_type> (expression)
reinterpret_cast <new_type> (expression)
dynamic_cast <new_type> (expression)
它們有著相同的結構,看起來像是模板方法。這些方法就是提供給開發者用來進行指針和引用的轉換的。
標準運算符的作用就是對傳統運算符的代替,以便做到統一。就像用std::endl來輸出換行,而不是'\n'。用代碼來說明相應的傳統轉換可以如何這些標準運算符。在標準運算符上,編譯器肯定有做更多的處理,特別是dynamic_cast是不能用傳統轉換方式來完全實現的。
const_cast (expression)
const_cast轉換符是用來移除變量的const或volatile限定符。它涉及到了多線程的設計,
用const_cast來去除const限定
對于const變量,不能修改它的值,這是這個限定符最直接的表現。
下邊的代碼顯然是達不到目的的: const int constant = 10;
int modifier = constant;
因為對modifier的修改并不會影響到constant,這暗示了一點:const_cast轉換符也不該用在對象數據上,因為這樣的轉換得到的兩個變量/對象并沒有相關性。
只有用指針或者引用,讓變量指向同一個地址才是解決方案,可惜下邊的代碼在C++中也是編譯不過的: const int constant = 21;
int* modifier = &constant
// Error: invalid conversion from 'const int*' to 'int*'
(上邊的代碼在C中是可以編譯的,最多會得到一個warning,所在在C中上一步就可以開始對constant里面的數據胡作非為了)
把constant交給非const的引用也是不行的。 const int constant = 21;
int& modifier = constant;
// Error: invalid initialization of reference of type 'int&' from expression of type 'const int'
于是const_cast就出來消滅const,以求引起程序世界的混亂。
下邊的代碼就順利編譯功過了: const int constant = 21;
const int* const_p = &constant;
int* modifier = const_cast<int*>(const_p);
*modifier = 7;
傳統轉換方式實現const_cast運算符
準轉換運算符是可以用傳統轉換方式實現的。const_cast實現原因就在于C++對于指針的轉換是任意的,它不會檢查類型,任何指針之間都可以進行互相轉換,因此const_cast就可以直接使用顯示轉換(int*)來代替: const int constant = 21;
const int* const_p = &constant;
int* modifier = (int*)(const_p);

或者可以把他們合成一個語句,跳過中間變量,用 const int constant = 21;
int* modifier = (int*)(&constant);

替代 const int constant = 21;
int* modifier = const_cast<int*>(&constant);
為何要去除const限定

從前面代碼中已經看到,不能對constant進行修改,但是可以對modifier進行重新賦值。
如果我們把結果打印出來: cout << "constant: "<< constant <<endl;
cout << "const_p: "<< *const_p <<endl;
cout << "modifier: "<< *modifier <<endl;
/**
constant: 21
const_p: 7
modifier: 7
**/

constant還是保留了它原來的值。
可是它們的確指向了同一個地址:
cout << "constant: "<< &constant <<endl;
cout << "const_p: "<< const_p <<endl;
cout << "modifier: "<< modifier <<endl;

/**
constant: 0x7fff5fbff72c
const_p: 0x7fff5fbff72c
modifier: 0x7fff5fbff72c
**/

說明C++里是const,就是const,const也沒有存在的意義了。
IBM的C++指南稱呼“*modifier = 7;”為“未定義行為(Undefined Behavior)”。所謂未定義,是說這個語句在標準C++中沒有明確的規定,由編譯器來決定如何處理。
位運算的左移操作也可算一種未定義行為,因為不確定是邏輯左移,還是算數左移。
再比如下邊的語句:v[i] = i++; 也是一種未定義行為,因為不知道是先做自增,還是先用來找數組中的位置。

對于未定義行為,能做的所要做的就是避免出現這樣的語句。對于const數據更要這樣保證:絕對不對const數據進行重新賦值。
調用了一個參數不是const的函數,而要傳進去的實際參數確實const的,但是知道這個函數是不會對參數做修改的。于是就需要使用const_cast去除const限定,以便函數能夠接受這個實際參數。
#include <iostream>
using namespace std;

void Printer (int* val,string seperator = "\n")
{
cout << val<< seperator;
}

int main(void)
{
const int consatant = 20;
//Printer(consatant);//Error: invalid conversion from 'int' to 'int*'
Printer(const_cast<int *>(&consatant));

return 0;
}
出現這種情況的原因,可能是所調用的方法是別人寫的。出現在const對象想調用自身的非const方法的時候,因為在類定義中,const也可以作為函數重載的一個標示符。有機會,會專門回顧一下我所知道const的用法,C++的const真的有太多可以說的了。
在IBM的C++指南中還提到了另一種可能需要去const的情況:
#include <iostream>
using namespace std;

int main(void) {
int variable = 21;
int* const_p = &variable;
int* modifier = const_cast<int*>(const_p);

*modifier = 7
cout << "variable:" << variable << endl;

return 0;
}
/**
variable:7
**/

定義了一個非const的變量,但用帶const限定的指針去指向它,
Director: Jim Fawcett
C++ Language Tutorial - Type Casting
Object Oriented Design
IBM Complilers - XL C/C++ V9.0 for Linux - The const_cast operator (C++ only)
stackoverflow: Is const_cast safe?



查看完整回答
反對 回復 2021-06-28
?
小唯快跑啊

TA貢獻1863條經驗 獲得超2個贊

顯式強制類型轉換(cast)包括以下操作符:
static_cast, dynamic_cast, const_cast, reinterpret_cast,對各種顯式類型轉換解釋:
static_cast:編譯器隱式執行的轉換都可以有static_cast顯式執行。
例子:
double num = 12.32;
int data = num;
這個例子完成了顯式類型轉換,當然我們完全可以顯式告訴編譯器我要轉換類型不且不關心轉換后精度損失,就可以寫成是:int data = static_cast<int>(num);

dynamic_cast:支持運行時識別指針或引用所指向的對象,如果綁定到引用或指針的對象不是目標類型的對象,則dynamic_cast失敗,如果轉換到指針類型的dynamic_cast失敗,則dynamic_cast的結果為0值;如果轉換到引用類型的dynamic_cast失敗,則拋出一個bad_cast類型的異常。
因此,dynamic_cast操作符一次執行兩個操作。首先驗證被請求的轉換是否有效,只有轉換有效,操作符才實際進行轉換。基類的指針可以賦值為指向派生類的對象,同樣,基類的引用也可以用派生類對象初始化,因此,dynamic_cast操作符執行的驗證必須在運行時進行。

const_cast:將轉換掉表達式的const性質.
例子:
const char * source = "zhangsan";
char * dest = source;
編譯出現錯誤提示:error C2440: 'initializing' : cannot convert from 'const char *' to 'char *'
這時我們可以運用const_cast去掉source的const性質。改為
char * dest = const_cast<char *>(source);就通過了編譯。

reinterpret_cast:顧名思義reinterpret:重新解釋。就是將操作數內容解釋為另一種不同的類型。這種強制轉換本質上依賴于機器,而且非常危險。

例子:
int * source ;
char *dest = reinterpret_cast<char *>(source);
如上,本來source本來指向的對象時int類型,但是想把這塊內存重新解釋為char類型,就用reinterpret_cast,但是這很危險,編程人員必須記住dest指向的真實對象其實是int類型。

你的例子問題在于,既然你用const定義常量,就不能改變a的值,但是你賦值了,所以錯誤。const_cast只是去掉const屬性,并沒說你可以改變其內容,只是可以講const定義的常量賦值給其他的變量而已。



查看完整回答
反對 回復 2021-06-28
  • 2 回答
  • 0 關注
  • 482 瀏覽
慕課專欄
更多

添加回答

舉報

0/150
提交
取消
微信客服

購課補貼
聯系客服咨詢優惠詳情

幫助反饋 APP下載

慕課網APP
您的移動學習伙伴

公眾號

掃描二維碼
關注慕課網微信公眾號