C++ explicit關鍵字詳解

http://www.cnblogs.com/ymy124/p/3632634.html

首先, C++中的explicit關鍵字只能用于修飾只有一個參數的類構造函數, 它的作用是表明該構造函數是顯示的, 而非隱式的, 跟它相對應的另一個關鍵字是implicit, 意思是隱藏的,類構造函數默認情況下即聲明為implicit(隱式).

那么顯示聲明的構造函數和隱式聲明的有什么區別呢? 我們來看下面的例子:

  1. class?CxString??//?沒有使用explicit關鍵字的類聲明,?即默認為隱式聲明??
  2. {??
  3. public:??
  4. ????char?*_pstr;??
  5. ????int?_size;??
  6. ????CxString(int?size)??
  7. ????{??
  8. ????????_size?=?size;????????????????//?string的預設大小??
  9. ????????_pstr?=?malloc(size?+?1);????//?分配string的內存??
  10. ????????memset(_pstr,?0,?size?+?1);??
  11. ????}??
  12. ????CxString(const?char?*p)??
  13. ????{??
  14. ????????int?size?=?strlen(p);??
  15. ????????_pstr?=?malloc(size?+?1);????//?分配string的內存??
  16. ????????strcpy(_pstr,?p);????????????//?復制字符串??
  17. ????????_size?=?strlen(_pstr);??
  18. ????}??
  19. ????//?析構函數這里不討論,?省略...??
  20. };??
  21. ??
  22. ????//?下面是調用:??
  23. ??
  24. ????CxString?string1(24);?????//?這樣是OK的,?為CxString預分配24字節的大小的內存??
  25. ????CxString?string2?=?10;????//?這樣是OK的,?為CxString預分配10字節的大小的內存??
  26. ????CxString?string3;?????????//?這樣是不行的,?因為沒有默認構造函數,?錯誤為:?“CxString”:?沒有合適的默認構造函數可用??
  27. ????CxString?string4("aaaa");?//?這樣是OK的??
  28. ????CxString?string5?=?"bbb";?//?這樣也是OK的,?調用的是CxString(const?char?*p)??
  29. ????CxString?string6?=?'c';???//?這樣也是OK的,?其實調用的是CxString(int?size),?且size等于'c'的ascii碼??
  30. ????string1?=?2;??????????????//?這樣也是OK的,?為CxString預分配2字節的大小的內存??
  31. ????string2?=?3;??????????????//?這樣也是OK的,?為CxString預分配3字節的大小的內存??
  32. ????string3?=?string1;????????//?這樣也是OK的,?至少編譯是沒問題的,?但是如果析構函數里用free釋放_pstr內存指針的時候可能會報錯,?完整的代碼必須重載運算符"=",?并在其中處理內存釋放??

上面的代碼中, "CxString string2 = 10;" 這句為什么是可以的呢? 在C++中, 如果的構造函數只有一個參數時, 那么在編譯的時候就會有一個缺省的轉換操作:將該構造函數對應數據類型的數據轉換為該類對象. 也就是說 "CxString string2 = 10;" 這段代碼, 編譯器自動將整型轉換為CxString類對象, 實際上等同于下面的操作:

  1. CxString?string2(10);??
  2. 或??
  3. CxString?temp(10);??
  4. CxString?string2?=?temp;??

但是, 上面的代碼中的_size代表的是字符串內存分配的大小, 那么調用的第二句 "CxString string2 = 10;" 和第六句 "CxString string6 = 'c';" 就顯得不倫不類, 而且容易讓人疑惑.?有什么辦法阻止這種用法呢? 答案就是使用explicit關鍵字. 我們把上面的代碼修改一下, 如下:

  1. class?CxString??//?使用關鍵字explicit的類聲明,?顯示轉換??
  2. {??
  3. public:??
  4. ????char?*_pstr;??
  5. ????int?_size;??
  6. ????explicit?CxString(int?size)??
  7. ????{??
  8. ????????_size?=?size;??
  9. ????????//?代碼同上,?省略...??
  10. ????}??
  11. ????CxString(const?char?*p)??
  12. ????{??
  13. ????????//?代碼同上,?省略...??
  14. ????}??
  15. };??
  16. ??
  17. ????//?下面是調用:??
  18. ??
  19. ????CxString?string1(24);?????//?這樣是OK的??
  20. ????CxString?string2?=?10;????//?這樣是不行的,?因為explicit關鍵字取消了隱式轉換??
  21. ????CxString?string3;?????????//?這樣是不行的,?因為沒有默認構造函數??
  22. ????CxString?string4("aaaa");?//?這樣是OK的??
  23. ????CxString?string5?=?"bbb";?//?這樣也是OK的,?調用的是CxString(const?char?*p)??
  24. ????CxString?string6?=?'c';???//?這樣是不行的,?其實調用的是CxString(int?size),?且size等于'c'的ascii碼,?但explicit關鍵字取消了隱式轉換??
  25. ????string1?=?2;??????????????//?這樣也是不行的,?因為取消了隱式轉換??
  26. ????string2?=?3;??????????????//?這樣也是不行的,?因為取消了隱式轉換??
  27. ????string3?=?string1;????????//?這樣也是不行的,?因為取消了隱式轉換,?除非類實現操作符"="的重載??

explicit關鍵字的作用就是防止類構造函數的隱式自動轉換.

上面也已經說過了,?explicit關鍵字只對有一個參數的類構造函數有效, 如果類構造函數參數大于或等于兩個時, 是不會產生隱式轉換的, 所以explicit關鍵字也就無效了.?例如:?

  1. class?CxString??//?explicit關鍵字在類構造函數參數大于或等于兩個時無效??
  2. {??
  3. public:??
  4. ????char?*_pstr;??
  5. ????int?_age;??
  6. ????int?_size;??
  7. ????explicit?CxString(int?age,?int?size)??
  8. ????{??
  9. ????????_age?=?age;??
  10. ????????_size?=?size;??
  11. ????????//?代碼同上,?省略...??
  12. ????}??
  13. ????CxString(const?char?*p)??
  14. ????{??
  15. ????????//?代碼同上,?省略...??
  16. ????}??
  17. };??
  18. ??
  19. ????//?這個時候有沒有explicit關鍵字都是一樣的??

但是, 也有一個例外, 就是當除了第一個參數以外的其他參數都有默認值的時候,?explicit關鍵字依然有效, 此時, 當調用構造函數時只傳入一個參數,?等效于只有一個參數的類構造函數, 例子如下:

  1. class?CxString??//?使用關鍵字explicit聲明??
  2. {??
  3. public:??
  4. ????int?_age;??
  5. ????int?_size;??
  6. ????explicit?CxString(int?age,?int?size?=?0)??
  7. ????{??
  8. ????????_age?=?age;??
  9. ????????_size?=?size;??
  10. ????????//?代碼同上,?省略...??
  11. ????}??
  12. ????CxString(const?char?*p)??
  13. ????{??
  14. ????????//?代碼同上,?省略...??
  15. ????}??
  16. };??
  17. ??
  18. ????//?下面是調用:??
  19. ??
  20. ????CxString?string1(24);?????//?這樣是OK的??
  21. ????CxString?string2?=?10;????//?這樣是不行的,?因為explicit關鍵字取消了隱式轉換??
  22. ????CxString?string3;?????????//?這樣是不行的,?因為沒有默認構造函數??
  23. ????string1?=?2;??????????????//?這樣也是不行的,?因為取消了隱式轉換??
  24. ????string2?=?3;??????????????//?這樣也是不行的,?因為取消了隱式轉換??
  25. ????string3?=?string1;????????//?這樣也是不行的,?因為取消了隱式轉換,?除非類實現操作符"="的重載??

以上即為C++?explicit關鍵字的詳細介紹.


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

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

相關文章

Fire!——兩個BFS

【題目描述】 【題目分析】 看到題目后很清楚是兩個BFS,可是我覺得對于火的BFS可以轉換成判斷,我的做法是將火的位置全部記錄下來,然后判斷某個位置距離每個火的步數是否小于當前步數,可是錯了,還不清楚為什么&#x…

函數調用過程(棧楨)

棧楨 首先來看一段代碼 #include<stdio.h> int add(int x, int y) {int z x y;return z; } int main() {int a 10;int b 20;int ret add(a, b);printf("ret %d\n",ret);return 0; } 此處是為了給a,b分別開辟空間,這時棧楨如圖所示 兩條push命令將a,b變…

C++智能指針簡單剖析

http://blog.csdn.net/lanxuezaipiao/article/details/41603883 導讀 最近在補看《C Primer Plus》第六版&#xff0c;這的確是本好書&#xff0c;其中關于智能指針的章節解析的非常清晰&#xff0c;一解我以前的多處困惑。C面試過程中&#xff0c;很多面試官都喜歡問智能指針相…

非常可樂——BFS

【題目描述】 大家一定覺的運動以后喝可樂是一件很愜意的事情&#xff0c;但是seeyou卻不這么認為。因為每次當seeyou買了可樂以后&#xff0c;阿牛就要求和seeyou一起分享這一瓶可樂&#xff0c;而且一定要喝的和seeyou一樣多。但seeyou的手中只有兩個杯子&#xff0c;它們的容…

整型數據存儲

//代碼1 #include<stdio.h> int main() {char a -1;signed char b -1;unsigned char c -1;printf("a %d, b %d, c %d", a, b, c);return 0; } 1000 0000 0000 0001 -> -1源碼 1111 1111 1111 1110 -> -1反碼 1111 1111 1111 1111 -> -1補碼 對于…

聊聊gcc參數中的-I, -L和-l

http://blog.csdn.net/stpeace/article/details/49408665 在本文中&#xff0c; 我們來聊聊gcc中三個常見的參數&#xff0c; 也即-I, -L和-l 一. 先說 -I (注意是大寫的i) 我們先來看簡單的程序&#xff1a; main.c: [cpp] view plaincopy #include <stdio.h> #incl…

Pots——BFS

【題目描述】 You are given two pots, having the volume of A and B liters respectively. The following operations can be performed: FILL(i) fill the pot i (1 ≤ i ≤ 2) from the tap; DROP(i) empty the pot i to the drain; POUR(i,j) pour from pot i to pot j;…

HDU - 4578Transformation——線段樹+區間加法修改+區間乘法修改+區間置數+區間和查詢+區間平方和查詢+區間立方和查詢

【題目描述】 HDU - 4578Transformation Problem Description Yuanfang is puzzled with the question below: There are n integers, a1, a2, …, an. The initial values of them are 0. There are four kinds of operations. Operation 1: Add c to each number between ax …

[C++基礎]034_C++模板編程里的主版本模板類、全特化、偏特化(C++ Type Traits)

http://www.cnblogs.com/alephsoul-alephsoul/archive/2012/10/18/2728753.html 1. 主版本模板類 首先我們來看一段初學者都能看懂&#xff0c;應用了模板的程序&#xff1a; 1 #include <iostream>2 using namespace std;3 4 template<class T1, class T2>5 clas…

自定義類型: 結構體,枚舉,聯合

1.結構體 個人認為結構體和數組特別相似&#xff0c;只不過結構體和數組的區別在于結構體的成員可以是不同類型&#xff0c;而數組成員類型是相同的。 &#xff08;1&#xff09;結構體的聲明 struct tag {成員列表//至少得有一個成員 }值列表;//值列表可以省略 struct {int a…

詳解C++中的函數調用和下標以及成員訪問運算符的重載

http://www.jb51.net/article/78436.htm 這篇文章主要介紹了詳解C中的函數調用和下標以及成員訪問運算符,講到了這些二元運算符使用的語法及重載,需要的朋友可以參考下函數調用 使用括號調用的函數調用運算符是二元運算符。 語法 ?1primary-expression ( expression-list )備…

A計劃——BFS

【題目描述】 可憐的公主在一次次被魔王擄走一次次被騎士們救回來之后&#xff0c;而今&#xff0c;不幸的她再一次面臨生命的考驗。魔王已經發出消息說將在T時刻吃掉公主&#xff0c;因為他聽信謠言說吃公主的肉也能長生不老。年邁的國王正是心急如焚&#xff0c;告招天下勇士…

使用openssl的md5庫

http://blog.csdn.net/sinat_35297665/article/details/78244523 在linux機器上&#xff0c;有一個命令可以計算出文件的md5值&#xff0c;那就是md5sum&#xff0c;如果沒有的話&#xff0c;就需要安裝RPM包&#xff1a;coreutils。 現在我們使用openssl的庫也可以方便的計算出…

主席樹入門

今天學習了一下主席樹&#xff08;名字這么強的嘛&#xff09; 雖然直接理解起來不容易&#xff0c;但是這種解決問題的思想其實并不陌生。 我們可以首先來看維護整個區間第K大的線段樹 我們將[l,r]區間內數字的多少用線段樹進行維護&#xff0c;這樣的話為了求取區間第k大&…

Socket網絡編程--小小網盤程序(1)

http://www.cnblogs.com/wunaozai/p/3886588.html 這個系列是準備講基于Linux Socket進行文件傳輸。簡單的文件傳輸就是客戶端可以上傳文件&#xff0c;可以從服務器端下載文件。就這么兩個功能如果再加上身份驗證&#xff0c;就成了FTP服務器了&#xff0c;如果對用戶的操作再…

使用 Verdaccio 構建自己的私有 npm 倉庫

前言 無論你是公司的開發者&#xff0c;還是個人開發者&#xff0c;你可能都聽說過或者使用過 npm&#xff0c;這是一個使用廣泛的 JavaScript 包管理器。但是&#xff0c;你是否遇到過以下的問題&#xff1a;你需要一個私有的包存放地方&#xff0c;或者你需要在離線環境下使…

HDU - 4348To the moon——主席樹+區間修改

HDU - 4348To the moon 【題目描述】 【題目分析】 題目中說明每次更新后時間都會加1&#xff0c;而且還會需要查詢以前的區間&#xff0c;還會需要返回以前的時間&#xff0c;所以是很裸的主席樹。區間查詢的話我們同樣需要用到lazy標記 通過這道題我發現線段樹的操作還是很靈…

進入一個目錄需要那些權限

1.文件訪問者的分類 文件的訪問者具體可分為以下幾類&#xff1a; (1)擁有者 (2)組擁有者 (3)其他用戶 這些都代表什么意思呢&#xff1f; 其中r表示只讀&#xff0c;w表示只寫&#xff0c;x表示可執行&#xff0c;第一個字母代表了文件的類型&#xff0c;其中文件類型可以分為…

Socket網絡編程--小小網盤程序(2)

http://www.cnblogs.com/wunaozai/p/3887728.html 這一節將不會介紹太多的技術的問題&#xff0c;這節主要是搭建一個小小的框架&#xff0c;為了方便接下來的繼續編寫擴展程序。本次會在上一小節的基礎上加上一個身份驗證的功能。 因為網盤程序不像聊天程序&#xff0c;網盤是…

Linux下的重要目錄

1.bin目錄 主要防止系統下的各種必備可執行文件 2./proc 目錄 這個目錄相當于Windows下的計算機系統信息查看以及進程動態查看&#xff0c;可以查看計算機信息&#xff0c;用來存放當前計算機上的進程信息 3./sys 目錄 (1)其中block目錄用于存放塊設備文件 (2)bus存放總線類型…