青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品

來吧,朋友!

為C++瘋狂

[轉(zhuǎn)帖] c++中的explicit關鍵字

 c++中的explicit關鍵字用來修飾類的構造函數(shù),表明該構造函數(shù)是顯式的,既然有"顯式"那么必然就有"隱式",那么什么是顯示而什么又是隱式的呢?

如果c++類的構造函數(shù)有一個參數(shù),那么在編譯的時候就會有一個缺省的轉(zhuǎn)換操作:將該構造函數(shù)對應數(shù)據(jù)類型的數(shù)據(jù)轉(zhuǎn)換為該類對象,如下面所示:
class MyClass
{
public:
MyClass( int num );
}
....
MyClass obj = 10; //ok,convert int to MyClass
在上面的代碼中編譯器自動將整型轉(zhuǎn)換為MyClass類對象,實際上等同于下面的操作:
MyClass temp(10);
MyClass obj = temp;
上面的所有的操作即是所謂的"隱式轉(zhuǎn)換"。

如果要避免這種自動轉(zhuǎn)換的功能,我們該怎么做呢?嘿嘿這就是關鍵字explicit的作用了,將類的構造函數(shù)聲明為"顯示",也就是在聲明構造函數(shù)的時候前面添加上explicit即可,這樣就可以防止這種自動的轉(zhuǎn)換操作,如果我們修改上面的MyClass類的構造函數(shù)為顯示的,那么下面的代碼就不能夠編譯通過了,如下所示:
class MyClass
{
public:
explicit MyClass( int num );
}
....
MyClass obj = 10; //err,can't non-explict convert

class isbn_mismatch:public std::logic_error{
public:
explicit isbn_missmatch(const std::string &s):std:logic_error(s){}
isbn_mismatch(const std::string &s,const std::string &lhs,const std::string &rhs):
std::logic_error(s),left(lhs),right(rhs){}
const std::string left,right;
virtual ~isbn_mismatch() throw(){}
};


Sales_item& operator+(const Sales_item &lhs,const Sales_item rhs)
{
if(!lhs.same_isbn(rhs))
   throw isbn_mismatch("isbn missmatch",lhs.book(),rhs.book());
Sales_item ret(lhs);
ret+rhs;
return ret;
}


Sales_item item1,item2,sum;
while(cin>>item1>>item2)
{
try{
   sun=item1+item2;
}catch(const isbn_mismatch &e)
{
   cerr<<e.what()<<"left isbn is:"<<e.left<<"right isbn is:"<<e.right<<endl;
}
}

用于用戶自定義類型的構造函數(shù),指定它是默認的構造函數(shù),不可用于轉(zhuǎn)換構造函數(shù).因為構造函數(shù)有三種:1拷貝構造函數(shù)2轉(zhuǎn)換構造函數(shù)3一般的構造函數(shù)(我自己的術語^_^)
另:如果一個類或結(jié)構存在多個構造函數(shù)時,explicit 修飾的那個構造函數(shù)就是默認的

class isbn_mismatch:public std::logic_error{
public:
explicit isbn_missmatch(const std::string &s):std:logic_error(s){}
isbn_mismatch(const std::string &s,const std::string &lhs,const std::string &rhs):
std::logic_error(s),left(lhs),right(rhs){}
const std::string left,right;
virtual ~isbn_mismatch() throw(){}
};


Sales_item& operator+(const Sales_item &lhs,const Sales_item rhs)
{
if(!lhs.same_isbn(rhs))
   throw isbn_mismatch("isbn missmatch",lhs.book(),rhs.book());
Sales_item ret(lhs);
ret+rhs;
return ret;
}


Sales_item item1,item2,sum;
while(cin>>item1>>item2)
{
try{
   sun=item1+item2;
}catch(const isbn_mismatch &e)
{
   cerr<<e.what()<<"left isbn is:"<<e.left<<"right isbn is:"<<e.right<<endl;
}
}

 

這個 《ANSI/ISO C++ Professional Programmer's Handbook 》是這樣說的

explicit Constructors
A constructor that takes a single argument is, by default, an implicit conversion operator, which converts its argument to
an object of its class (see also Chapter 3, "Operator Overloading"). Examine the following concrete example:
class string
{
private:
int size;
int capacity;
char *buff;
public:
string();
string(int size); // constructor and implicit conversion operator
string(const char *); // constructor and implicit conversion operator
~string();
};
Class string has three constructors: a default constructor, a constructor that takes int, and a constructor that
constructs a string from const char *. The second constructor is used to create an empty string object with an
initial preallocated buffer at the specified size. However, in the case of class string, the automatic conversion is
dubious. Converting an int into a string object doesn't make sense, although this is exactly what this constructor does.

Consider the following:
int main()
{
string s = "hello"; //OK, convert a C-string into a string object
int ns = 0;
s = 1; // 1 oops, programmer intended to write ns = 1,
}
In the expression s= 1;, the programmer simply mistyped the name of the variable ns, typing s instead. Normally,
the compiler detects the incompatible types and issues an error message. However, before ruling it out, the compiler first
searches for a user-defined conversion that allows this expression; indeed, it finds the constructor that takes int.
Consequently, the compiler interprets the expression s= 1; as if the programmer had written
s = string(1);
You might encounter a similar problem when calling a function that takes a string argument. The following example
can either be a cryptic coding style or simply a programmer's typographical error. However, due to the implicit
conversion constructor of class string, it will pass unnoticed:
int f(string s);
int main()
{
f(1); // without a an explicit constructor,
//this call is expanded into: f ( string(1) );
//was that intentional or merely a programmer's typo?
}
'In order to avoid such implicit conversions, a constructor that takes one argument needs to be declared explicit:
class string
{
//...
public:
explicit string(int size); // block implicit conversion
string(const char *); //implicit conversion
~string();
};
An explicit constructor does not behave as an implicit conversion operator, which enables the compiler to catch the
typographical error this time:
int main()
{
string s = "hello"; //OK, convert a C-string into a string object
int ns = 0;
s = 1; // compile time error ; this time the compiler catches the typo
}
Why aren't all constructors automatically declared explicit? Under some conditions, the automatic type conversion is
useful and well behaved. A good example of this is the third constructor of string:
string(const char *);

The implicit type conversion of const char * to a string object enables its users to write the following:
string s;
s = "Hello";
The compiler implicitly transforms this into
string s;
//pseudo C++ code:
s = string ("Hello"); //create a temporary and assign it to s
On the other hand, if you declare this constructor explicit, you have to use explicit type conversion:
class string
{
//...
public:
explicit string(const char *);
};
int main()
{
string s;
s = string("Hello"); //explicit conversion now required
return 0;
}
Extensive amounts of legacy C++ code rely on the implicit conversion of constructors. The C++ Standardization
committee was aware of that. In order to not make existing code break, the implicit conversion was retained. However, a
new keyword, explicit, was introduced to the languageto enable the programmer to block the implicit conversion
when it is undesirable. As a rule, a constructor that can be invoked with a single argument needs to be declared
explicit. When the implicit type conversion is intentional and well behaved, the constructor can be used as an
implicit conversion operator.

網(wǎng)上找的講的最好的貼:

C++ 中 explicit 關鍵字的作用
在 C++ 中, 如果一個類有只有一個參數(shù)的構造函數(shù),C++ 允許一種特殊的聲明類變量的方式。在這種情況下,可以直接將一個對應于構造函數(shù)參數(shù)類型的數(shù)據(jù)直接賦值給類變量,編譯器在編譯時會自動進行類型轉(zhuǎn)換,將對應于構造函數(shù)參數(shù)類型的數(shù)據(jù)轉(zhuǎn)換為類的對象。 如果在構造函數(shù)前加上 explicit 修飾詞, 則會禁止這種自動轉(zhuǎn)換,在這種情況下,即使將對應于構造函數(shù)參數(shù)類型的數(shù)據(jù)直接賦值給類變量,編譯器也會報錯。

下面以具體實例來說明。

建立people.cpp 文件,然后輸入下列內(nèi)容:

class People
{
public:
int age;
explicit People (int a)
 {
  age=a;
 }
};
void foo ( void )
{
 People p1(10);  //方式一
 People* p_p2=new People(10); //方式二
 People p3=10; //方式三
}
這段 C++ 程序定義了一個類 people ,包含一個構造函數(shù), 這個構造函數(shù)只包含一個整形參數(shù) a ,可用于在構造類時初始化 age 變量。

然后定義了一個函數(shù)foo,在這個函數(shù)中我們用三種方式分別創(chuàng)建了三個10歲的“人”。第一種是最一般的類變量聲明方式。第二種方式其實是聲明了一個people類的指針變量,然后在堆中動態(tài)創(chuàng)建了一個people實例,并把這個實例的地址賦值給了p_p2。第三種方式就是我們所說的特殊方式,為什么說特殊呢?我們都知道,C/C++是一種強類型語言,不同的數(shù)據(jù)類型是不能隨意轉(zhuǎn)換的,如果要進行類型轉(zhuǎn)換,必須進行顯式強制類型轉(zhuǎn)換,而這里,沒有進行任何顯式的轉(zhuǎn)換,直接將一個整型數(shù)據(jù)賦值給了類變量p3。

因此,可以說,這里進行了一次隱式類型轉(zhuǎn)換,編譯器自動將對應于構造函數(shù)參數(shù)類型的數(shù)據(jù)轉(zhuǎn)換為了該類的對象,因此方式三經(jīng)編譯器自動轉(zhuǎn)換后和方式一最終的實現(xiàn)方式是一樣的。

不相信? 耳聽為虛,眼見為實,讓我們看看底層的實現(xiàn)方式。

為了更容易比較方式一和方式三的實現(xiàn)方式,我們對上面的代碼作一點修改,去除方式二:

void foo ( void )
{
 People p1(10);  //方式一
 People p3=10; //方式三
}
去除方式二的原因是方式二是在堆上動態(tài)創(chuàng)建類實例,因此會有一些額外代碼影響分析。修改完成后,用下列命令編譯 people.cpp

$ gcc -S people.cpp

"-S"選項是GCC輸出匯編代碼。命令執(zhí)行后,默認生成people.s。 關鍵部分內(nèi)容如下:

.globl _Z3foov
.type _Z3foov, @function
_Z3foov:
.LFB5:
 pushl %ebp
.LCFI2:
 movl %esp, %ebp
.LCFI3:
 subl $24, %esp
.LCFI4:
 movl $10, 4(%esp)
 leal -4(%ebp), %eax
 movl %eax, (%esp)
 call _ZN6PeopleC1Ei
 movl $10, 4(%esp)
 leal -8(%ebp), %eax
 movl %eax, (%esp)
 call _ZN6PeopleC1Ei
 leave
 ret

看“.LCFI4” 行后面的東西,1-4行和5-8行幾乎一模一樣,1-4行即為方式一的匯編代碼,5-8即為方式三的匯編代碼。 細心的你可能發(fā)現(xiàn)2和6行有所不同,一個是 -4(%ebp) 而另一個一個是 -8(%ebp) ,這分別為類變量P1和P3的地址。

對于不可隨意進行類型轉(zhuǎn)換的強類型語言C/C++來說, 這可以說是C++的一個特性。哦,今天好像不是要說C++的特性,而是要知道explicit關鍵字的作用?

explicit關鍵字到底是什么作用呢? 它的作用就是禁止這個特性。如文章一開始而言,凡是用explicit關鍵字修飾的構造函數(shù),編譯時就不會進行自動轉(zhuǎn)換,而會報錯。

讓我們看看吧! 修改代碼:

class People
{
public:
int age;
explicit People (int a)
 {
  age=a;
 }
};
然后再編譯:
$ gcc -S people.cpp
編譯器立馬報錯:
people.cpp: In function ‘void foo()’:
people.cpp:23: 錯誤:請求從 ‘int’ 轉(zhuǎn)換到非標量類型 ‘People’

posted on 2009-07-24 16:49 yanghaibao 閱讀(244) 評論(0)  編輯 收藏 引用

導航

<2025年12月>
30123456
78910111213
14151617181920
21222324252627
28293031123
45678910

統(tǒng)計

常用鏈接

留言簿

隨筆分類

隨筆檔案

文章檔案

收藏夾

Good blogs

搜索

最新評論

閱讀排行榜

評論排行榜

青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品
  • <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>
            亚洲精品国产精品乱码不99| 一二三四社区欧美黄| 亚洲欧美日韩电影| 国产精品一卡| 欧美亚洲综合在线| 小嫩嫩精品导航| 黄色在线一区| 欧美激情欧美激情在线五月| 久久夜色精品国产欧美乱极品| 看片网站欧美日韩| 欧美freesex8一10精品| 日韩一级精品视频在线观看| 妖精成人www高清在线观看| 欧美视频网址| 久久久久久网址| 欧美成人免费在线| 亚洲伊人伊色伊影伊综合网| 亚洲字幕一区二区| 亚洲承认在线| 一区二区三区欧美激情| 国产日韩在线不卡| 亚洲第一福利在线观看| 欧美日韩一区二区在线观看视频| 亚洲男人天堂2024| 久久精品青青大伊人av| 亚洲巨乳在线| 校园春色综合网| 9l国产精品久久久久麻豆| 亚洲一二三区精品| 亚洲韩国精品一区| 亚洲小说欧美另类婷婷| 精东粉嫩av免费一区二区三区| 亚洲精品乱码久久久久久蜜桃麻豆 | 欧美一区二区三区视频免费| 久久麻豆一区二区| 午夜影院日韩| 免费在线欧美黄色| 久久国产婷婷国产香蕉| 欧美日韩大片| 乱码第一页成人| 国产精品狼人久久影院观看方式| 免费不卡亚洲欧美| 国产精品亚洲第一区在线暖暖韩国| 免费观看一级特黄欧美大片| 国产精品盗摄久久久| 欧美国产在线观看| 国产欧美日韩另类视频免费观看 | 亚洲欧美日韩成人| 米奇777在线欧美播放| 欧美在线电影| 欧美日韩国产不卡| 欧美激情1区2区3区| 国产小视频国产精品| 日韩视频一区二区三区在线播放| 一区免费视频| 欧美一区三区二区在线观看| 亚洲女与黑人做爰| 欧美日韩国产在线一区| 欧美激情亚洲| 亚洲国产一区二区三区在线播| 欧美一级网站| 久久久久久久综合色一本| 欧美色播在线播放| 日韩午夜免费视频| 亚洲午夜av| 欧美日本一道本| 亚洲人成在线观看一区二区| 亚洲国产婷婷| 欧美电影在线| 国产精品日韩一区二区| 一本色道久久综合亚洲精品婷婷| 亚洲免费观看高清完整版在线观看| 美女被久久久| 亚洲激情成人网| 亚洲美女一区| 欧美日一区二区三区在线观看国产免| 亚洲国产天堂久久综合| 99在线观看免费视频精品观看| 欧美精品一区二区三区一线天视频| 亚洲成色www8888| 日韩午夜三级在线| 欧美午夜一区二区福利视频| 亚洲图片欧洲图片日韩av| 性色一区二区| 精品999成人| 欧美搞黄网站| 亚洲夜间福利| 美日韩精品免费| 亚洲精品九九| 国产精品专区第二| 另类激情亚洲| 制服诱惑一区二区| 久久久久久午夜| 亚洲精品一区二区网址| 国产精品久久久久久久久久免费| 亚洲一区www| 久久一区二区三区超碰国产精品| 亚洲国产va精品久久久不卡综合| 欧美精品综合| 欧美一区二区三区男人的天堂| 另类春色校园亚洲| 中文国产亚洲喷潮| 黄色精品一区二区| 欧美日韩综合视频网址| 性伦欧美刺激片在线观看| 欧美激情一区二区久久久| 亚洲欧美久久久久一区二区三区| 国内免费精品永久在线视频| 欧美激情一区二区三区| 性18欧美另类| 亚洲美女黄网| 欧美风情在线观看| 欧美一级淫片播放口| 亚洲精品国产精品乱码不99| 国产精品人成在线观看免费| 欧美va亚洲va日韩∨a综合色| 中国av一区| 亚洲精品美女久久7777777| 久久亚洲高清| 欧美亚洲自偷自偷| 99在线热播精品免费| 一色屋精品亚洲香蕉网站| 欧美性猛交一区二区三区精品| 久久综合给合| 欧美一区视频| 亚洲综合色网站| 一区二区成人精品| 亚洲精品视频免费| 欧美激情导航| 蜜桃精品久久久久久久免费影院| 亚洲女性裸体视频| 中文国产一区| 亚洲最新中文字幕| 亚洲区一区二区三区| 在线观看不卡av| 国产真实乱子伦精品视频| 国产精品久久久一本精品| 欧美日韩免费高清| 欧美激情按摩| 亚洲一区二区三区中文字幕| 亚洲破处大片| 亚洲激情一区二区| 亚洲国产精品久久精品怡红院| 激情婷婷欧美| 亚洲第一精品福利| 一区二区自拍| 亚洲欧洲精品一区二区三区不卡 | 亚洲电影在线| 韩国av一区二区三区四区| 国产亚洲一区二区在线观看| 国产日韩在线一区| 国产主播喷水一区二区| 国产亚洲精品aa午夜观看| 国产欧美日韩精品一区| 国产伦精品一区二区三区视频黑人 | 亚洲精品国产品国语在线app| 亚洲大胆av| 亚洲三级毛片| 日韩视频在线免费观看| 99这里只有精品| 亚洲天堂久久| 欧美一区二区三区四区在线观看| 欧美有码在线观看视频| 欧美在线观看日本一区| 老司机一区二区三区| 欧美国产日韩一区二区| 欧美日韩亚洲高清一区二区| 国产精品国产三级国产aⅴ无密码 国产精品国产三级国产aⅴ入口 | 欧美中文字幕久久| 久久婷婷成人综合色| 欧美成人黑人xx视频免费观看| 亚洲国产精品久久人人爱蜜臀 | av成人动漫| 亚洲欧美一区二区三区极速播放 | 奶水喷射视频一区| 欧美日韩精品免费观看视频| 国产精品久久久久久五月尺| 黑丝一区二区| 亚洲网站在线| 久久综合色婷婷| 一本大道久久a久久精品综合| 久久aⅴ乱码一区二区三区| 蜜臀久久99精品久久久画质超高清| 欧美日韩在线三区| 国一区二区在线观看| 99精品国产在热久久婷婷| 久久激情五月激情| 亚洲国产午夜| 久久成人一区| 欧美日韩中文字幕精品| 狠狠色香婷婷久久亚洲精品| 亚洲视频在线观看三级| 久热成人在线视频| 99精品视频免费观看| 老司机精品导航| 国产农村妇女毛片精品久久莱园子 | 欧美国产在线视频| 国产综合色精品一区二区三区| 99在线精品观看| 欧美成人中文|