char类型的实参与const char类型的形参不兼容_C++干货系列——顶层const和底层const...
頂層 const 和底層 const
學C++的小伙伴是不是被const機制搞得暈頭轉向,永遠都記不住哪個是指針不能變哪個是指針指向的對象不能變?純靠記憶肯定不行,理解透徹才能一勞永逸。本文詳細介紹了C++的頂層和底層const機制,幫你深入了解以上問題的核心和相關問題的拓展,小白也能看懂!一起來看看吧。
從 const 指針開始說起。const int* pInt; 和 int *const pInt = &someInt;,前者是 *pInt 不能改變,而后者是 pInt 不能改變。因此指針本身是不是常量和指針所指向的對象是不是常量就是兩個互相獨立的問題。用頂層表示指針本身是個常量,底層表示指針所指向的對象是個常量。
更一般的,頂層 const 可以表示任意的對象是常量,這一點對任何數據類型都適用;底層 const 則與指針和引用等復合類型有關,比較特殊的是,指針類型既可以是頂層 const 也可以是底層 const 或者二者兼備。
拷貝與頂層和底層 const
int i = 0; int *const p1 = &i; // 不能改變 p1 的值,這是一個頂層 const int ci = 42; // 不能改變 ci 的值,這是一個頂層 const int *p2 = &ci; // 允許改變 p2 的值,這是一個底層 const int *const p3 = p2; // 靠右的 const 是頂層 const,靠左的是底層 const const int &r = ci; // 所有的引用本身都是頂層 const,因為引用一旦初始化就不能再改為其他對象的引用,這里用于聲明引用的 const 都是底層 const當執行對象的拷貝操作時,常量是頂層const還是底層const的區別明顯。其中,頂層 const 不受什么影響。
i = ci; // 正確:拷貝 ci 的值給 i,ci 是一個頂層 const,對此操作無影響。 p2 = p3; // 正確:p2 和 p3 指向的對象相同,p3 頂層 const 的部分不影響。與此相對的,底層 const 的限制卻不能被忽視。當執行對象的拷貝操作時,拷入和拷出的對象必須具有相同的底層 const 資格,或者兩個對象的數據類型必須能夠轉換,一般來說,非常量可以轉化為常量,反之不行。
int *p = p3; // 錯誤:p3 包含底層 const 的定義,而p沒有。假設成功,p 就可以改變 p3 指向的對象的值。 p2 = p3; // 正確:p2 和 p3 都是底層 const p2 = &i; // 正確:int* 能夠轉化為 const int*,這也是形參是底層const的函數形參傳遞外部非 const 指針的基礎。 int &r = ci; // 錯誤:普通 int& 不能綁定到 int 常量中。 const int &r2 = i; // 正確:const int& 可以綁定到一個普通 int 上。函數重載與頂層和底層 const 形參
頂層 const 不影響傳入函數的對象,一個擁有頂層 const 的形參無法和另一個沒有頂層 const 的形參區分開:
Record lookup(Phone); Record lookup(const Phone); //重復聲明了Record lookup(Phone) ? Record lookup(Phone*); Record lookup(Phone* const); //該const是頂層,重復聲明了Record lookup(Phone* const)另一方面,如果形參是某種類型的指針或引用,則通過區分其是否指向的是常量對象還是非常量對象可以實現函數重載。此時的const是底層的。
Record lookup(Phone&); Record lookup(const Phone&); //正確,底層const實現了函數的重載 ? Record lookup(Phone*); Record lookup(const Phone*); //正確,底層const實現了函數的重載函數重載與強制類型轉換
以下節選自《Effective C++》,假設要重載一個函數,而重載函數的區別僅在于函數形參一個是底層const一個是非底層的,那么最佳的做法是采用代碼的復用,減少這兩個重載函數實現過程的相同代碼段,可以通過const_cast來實現這一做法,在非const函數中調用const。
class Textbook { public:...const char& operator[](std::size_t position) const {...return text[position];}char& operator[](std::size_t position){//這里首先將op[]的返回值的const去除,因為const char&不能自動轉換為char&,除此之外,由于調用以上const函數的必須是const對象,因此將調用此函數的對象(即*this)強制轉化為一個(底層)const對象,再調用const op[]。returnconst_cast<char&>(static_cast<const TextBlock&>(*this)[position]);} };相關問題:
為什么不能在一個常量對象中調用非常成員函數?
因為在默認情況下,this的類型是指向類的非常量版本的常量指針(意思是this的值不能改變,永遠指向那個對象,即“常量指針”,但是被this指向的對象本身是可以改變的,因為是非常量版本,這里this相當于是頂層const),而this盡管是隱式的,它仍然需要遵循初始化規則,普通成員函數的隱式參數之一是一個底層非const指針,在默認情況下我們無法把一個底層const的this指針轉化為非const的this指針,因此我們不能在常量對象上調用普通的成員函數。因此在上例中,形參列表后的const就意味著默認this指針應該是一個底層const, 類型是 const ClassName&。而非常對象卻可以調用常成員函數,因為底層非const可以默認轉化為底層const。
一些拙見,如有錯誤,還望讀者指正。
這篇文章收錄在我的專欄中哦:
C++干貨系列?zhuanlan.zhihu.com點個關注,及時獲得最新干貨。
總結
以上是生活随笔為你收集整理的char类型的实参与const char类型的形参不兼容_C++干货系列——顶层const和底层const...的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 博途创建vb脚本实例_基于博途V15 西
- 下一篇: 计算机中丢失vcomp140.dll,V