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

首先,any類里面一定要提供一個模板構(gòu)造函數(shù)和模板operator=操作符。其次,數(shù)據(jù)的存放之所是個問題,顯然你不能將它保存在any類中,那會導(dǎo)致any類成為模板類,后者是明確不被允許的。結(jié)論是:為容器準(zhǔn)備一個非泛型的基類,而讓指針指向該基類。

動機

C++是強類型語言,所有強類型語言對類型的要求都是苛刻的,類型一有不合編譯器就會抱怨說不能將某某類型轉(zhuǎn)換為某某類型,當(dāng)然如果在類型之間提供了轉(zhuǎn)換操作符或是標(biāo)準(zhǔn)所允許的一定程度的隱式轉(zhuǎn)換(如經(jīng)過非explicit構(gòu)造函數(shù)創(chuàng)建臨時變量的隱式轉(zhuǎn)換或是在intlong這些基本類型間的)又另當(dāng)別論。總的說來,為了保持類型安全,C++有嚴(yán)厲的要求。然而有時候程序員可能有這樣的需要:

 

int i;

iong j;

X x; // 假設(shè)X為用戶定義的類

 

any anyVal=i;

... //use anyVal as a int value

 

anyVal=j;

... //use anyVal as a long value

 

anyVal=x;

... //use anyVal as a long value

 

考慮這樣的一個泛型指針類該如何設(shè)計是很有趣的事情。

 

1. 它本身不能是模板類,因為如果它是模板,你必須為它的具現(xiàn)化提供模板參數(shù)。而事實上你并不想這樣做。你想同一個對象接受任意類型的數(shù)據(jù)。在上面的代碼中這個對象是anyVal。然而,如果你必須為它提供模板參數(shù),那么上面的代碼看起來就會像這樣:

 

any<int> anyIntVal=i;

any<long> anyLongVal=j;

...

 

這顯然已經(jīng)喪失了anyVal的優(yōu)勢——以單個對象接受所有類型的數(shù)據(jù)。與其這樣還不如直接寫:

 

int anyIntVal=i;

int anyLongVal=j;

 

所以,any不能是模板類。

 

2. 它必須提供某些有關(guān)它所保存的對象類型的信息。

 

3. 它必須提供某種方法將它保存的數(shù)值取出來

 

事實上,boost庫已經(jīng)提供了這樣的類boost::any,下面我就為你講述它的原理及構(gòu)造。

 

boost::any原理與結(jié)構(gòu)

首先,any類里面一定要提供一個模板構(gòu)造函數(shù)和模板operator=操作符。因為你必須允許用戶寫出:

 

any any_value(val); //val 的類型為任意的

any_value=val1; //val1 類型也是任意的

 

這樣的代碼。

 

其次,數(shù)據(jù)的存放之所是個問題,顯然你不能將它保存在any類中,那會導(dǎo)致any類成為模板類,后者是明確不被允許的。數(shù)據(jù)應(yīng)該動態(tài)存放,即動態(tài)分配一個數(shù)據(jù)的容器來存放數(shù)據(jù),而any類中則保存指向這個容器的指針,明確地說,是指向這個容器的基類的指針,這是因為容器本身必須為模板,而any類中的指針成員又必須不是泛型的(因為any不能是泛型的,所以any中所有數(shù)據(jù)成員都不能是泛型的),所以,結(jié)論是:為容器準(zhǔn)備一個非泛型的基類,而讓指針指向該基類

 

下面就看一看boost庫是如何具體實現(xiàn)這兩點的。

 

摘自”boost/any.hpp”

 

class any

{

public:

 

class placeholder // 泛型數(shù)據(jù)容器holder的非泛型基類  

{                   

public:

// 虛析構(gòu)函數(shù),為保證派生類對象能用基類指針析構(gòu)

virtual ~placeholder(){}

 

public:

  // 提供關(guān)于類型的信息

virtual const std::type_info & type() const = 0;

virtual placeholder * clone() const = 0;  // 復(fù)制

}; // placeholder

 

template<typename ValueType>

class holder : public placeholder

{

public:

holder(const ValueType & value)

: held(value)

{}

public:

virtual const std::type_info & type() const

{

  // typeid返回std::typeinfo對象引用,后者包含任意對象的類型信息, name,此外還提供operator==操作符你可以用typeid(oneObj)==typeid(anotherObj)來比兩個對象之類型是否一致。

return typeid(ValueType); 

}

 

virtual placeholder * clone() const

{

return new holder(held);  // 改寫虛函數(shù),返回自身的復(fù)制體

}

 

public:

ValueType held; // 數(shù)據(jù)保存的地方

}; // holder

 

// 指向泛型數(shù)據(jù)容器holder的基類placeholder的指針

placeholder * content;

 

//模板構(gòu)造函數(shù),動態(tài)分配數(shù)據(jù)容器并調(diào)用其構(gòu)造函數(shù)

template<typename ValueType>

any(const ValueType & value)

: content(new holder<ValueType>(value))

{}

...

// 與模板構(gòu)造函數(shù)一樣,但使用了swap慣用手法

template<typename ValueType>

any & operator=(const ValueType & rhs)

{

// 先創(chuàng)建一個臨時對象any(rhs),再調(diào)用下面的swap函數(shù)進(jìn)行底層數(shù)據(jù)交換,注意與*this交換數(shù)據(jù)的是臨時對象,所以rhs的底層數(shù)據(jù)并未被更改,只是在swap結(jié)束后臨時對象擁有了*this的底層數(shù)據(jù),而此時*this也擁有了臨時對象構(gòu)造時所擁有的rhs的數(shù)據(jù)的副本。然后臨時對象由于生命期的結(jié)束而被自動析構(gòu),*this原來的底層數(shù)據(jù)隨之煙消云散。

any(rhs).swap(*this);

return *this;

}

 

any & swap(any & rhs) //swap函數(shù),交換底層數(shù)據(jù)

{

std::swap(content, rhs.content); // 只是簡單地將兩個指針的值互換

return *this;

}

 

~any()  //析構(gòu)函數(shù)

{

  //釋放容器,用的是基類指針,這就是placeholder需要一個虛析構(gòu)函數(shù)的原因

delete content;

}

...

};

 

這雖然并非any的全部源代碼,但是所有重要的思想已經(jīng)表露無遺。剩下的部分只是一些簡單的細(xì)節(jié),請參見boost庫的原文件。

 

但是等等!,你急切的說:你失去了類型的信息。...的確,當(dāng)賦值的模板函數(shù)返回后你也就失去了關(guān)于類型的信息。考慮下面你可能想要寫出的代碼:

 

int i=10;

boost::any anyVal=i;

 

int j=anyVal;

// error,實際上你是想把anyVal賦給另一個int型變量,這應(yīng)該以某種方式被允許,但決不是在any類中提供轉(zhuǎn)換操作符,因為你事先并不知道要用anyVal來承載何種類型的變量,所以轉(zhuǎn)換操作符無從給出。

 

當(dāng)轉(zhuǎn)換操作符的設(shè)想徹底失敗后,我們只能借助于某些外來的顯式轉(zhuǎn)換操作。就向static_cast<>一樣。boost提供了any_cast<>,于是你可以這樣寫:

 

int j=any_cast<int>(anyVal);

 

事實上,any_cast的代碼是這樣的:

 

template<typename ValueType>

ValueType any_cast(const any & operand)

{

  // 調(diào)用any_cast針對指針的版本。

const ValueType * result = any_cast<ValueType>(&operand);

 

// 如果cast失敗,即實際 保存的并非ValueType型數(shù)據(jù),則拋出一個異常。

if(!result)

throw bad_any_cast(); // 派生自std::bad_cast

return *result;

}

 

any_cast針對指針的版本是這樣:

 

template<typename ValueType>

ValueType * any_cast(any * operand)

{

  // 這個類型檢查很重要,后面會對它作更詳細(xì)的解釋

return

operand &&

(operand->type()==typeid(ValueType)) ? // #1

&static_cast<any::holder<ValueType>*>(operand->content)->held

: 0; // 這兒有個向下類型轉(zhuǎn)換

}

 

 

這兩個any_cast版本應(yīng)該很好理解。此外后一個版本中#1處的類型檢查也是必要的,如果沒有這個檢查,考慮以下代碼:

 

int i=10;

boost::any anyVal=i;

 

//如果沒有那個類型檢查,這將通過編譯且運行期通常也不會出錯,但是對d的賦值將會是非常奇怪的情形。

double d=any_cast<double>(anyVal);

 

這將通過編譯,且運行期通常竟然也不會出錯,下面我為你解釋為什么會這樣。

 

boost::anyVal=i;其實將anyVal.content指針指向了一個holder<int>對象(請回顧上面的代碼)。然后any_cast<double>(anyVal)實際上調(diào)用了any_cast<>針對指針的重載版本,并將anyVal的地址傳遞過去,也就是轉(zhuǎn)到#1處,因為調(diào)用的是any_cast<double>,所以#1處的代碼被編譯器實例化為:

 

// #2

static_cast<any::holder<double> *>(operand->content)->held

 

但是前面說過,operand->content實際指向的是any::holder<int>,所以這個static_cast非法的,然而事實是:它能通過編譯!原因很簡單: holder<double>placeholder的派生類,而operand->content的類型正是placeholder。從基類指針到派生類指針的轉(zhuǎn)換被認(rèn)為是合法的。但這卻釀成大錯,因為表達(dá)式#2的類型將因此被推導(dǎo)為double!原先holder<int>只給int held;成員分配了sizeof(int)個字節(jié)的內(nèi)存,而現(xiàn)在卻要將int型的held當(dāng)作double型來使用,也就是說使用sizeof(double)個字節(jié)內(nèi)存。所以這就相當(dāng)于:

 

int i=10;

double* pd=(double*)(void*)&i;

 

// 行為未定義,但通常卻不會出錯,然而隱藏的錯誤更可怕,你得到的d的值幾乎肯定不是你想要的。

double d=*pd;

 

使用typeinfo讓我們有可能在運行時發(fā)現(xiàn)這種類型不符并及時拋出異常。但有個違反直觀的事情是上面的那行錯誤的代碼仍能通過編譯,并且你也無法阻止它通過編譯,因為holder<int>holder<double>都是placeholder的基類。所以只能期望程序員們清楚自己在做什么,要不然就給他個異常瞧瞧。

 

使用boost::any實現(xiàn)virtual template成員函數(shù)

如你所知,C++中沒有提供virtual template function。然而有時候你的確會有這種需要,any可以一定程度上滿足這種需要,例如,

 

class Base

{

public:

virtual void Accept(boost::any anyData)

{

...

}

};

class Derived:public Base

{

public:

virtual void Accept(boost::any anyData)

{

...

}

};

 

這樣的Accept函數(shù)能夠接受任意類型的數(shù)據(jù),并且是virtual函數(shù)。

目錄(展開《boost源碼剖析》系列文章)

本文來自:http://blog.csdn.net/pongba/archive/2004/08/24/82811.aspx

posts - 94, comments - 138, trackbacks - 0, articles - 94

Copyright © RichardHe

青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品
  • <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>
            国产一区二区在线观看免费| 快射av在线播放一区| 欧美fxxxxxx另类| 欧美亚一区二区| 免费视频最近日韩| 欧美日韩一区二区三区在线| 六月婷婷一区| 亚洲黄色高清| 欧美日韩久久精品| 激情成人在线视频| 香蕉成人伊视频在线观看| 亚洲午夜视频| 国产精品高清免费在线观看| 亚洲高清网站| 一区二区三区在线看| 另类尿喷潮videofree| 亚洲国产精品久久91精品| 亚洲人久久久| 国产精品爽爽爽| 久久一区精品| 亚洲视频精选在线| 久久gogo国模裸体人体| 在线欧美三区| 欧美视频精品一区| 午夜一区二区三区在线观看| 欧美v亚洲v综合ⅴ国产v| aa级大片欧美三级| 国内自拍视频一区二区三区| 国产精品ⅴa在线观看h| 99国产一区| 亚洲第一毛片| 久久综合999| 欧美一区二区三区在线免费观看| 亚洲国产精品美女| 国产亚洲成av人在线观看导航| 欧美a级片网| 久久午夜精品一区二区| 亚洲精品久久久久久下一站 | 久久蜜臀精品av| 亚洲欧美一区二区原创| 一区二区三区精密机械公司| 亚洲国产一区视频| 亚洲国产高清在线| 亚洲精品久久久久| 国产曰批免费观看久久久| 欧美日韩精品一区二区天天拍小说| 久久一二三国产| 老司机午夜免费精品视频 | 免播放器亚洲| 裸体丰满少妇做受久久99精品| 久久久久久午夜| 免费一级欧美片在线观看| 久久精品国产清自在天天线| 欧美一级在线亚洲天堂| 久久国产天堂福利天堂| 女人香蕉久久**毛片精品| 美女网站久久| 亚洲免费激情| 欧美一区二区三区在线观看| 久久精彩视频| 久久这里只有| 欧美成年视频| 国产麻豆一精品一av一免费| 在线日韩av片| 午夜精品视频网站| 欧美精品播放| 一区二区在线视频| 午夜激情综合网| 最新69国产成人精品视频免费| 亚洲人成网站精品片在线观看 | 欧美日韩亚洲综合| 黄色亚洲免费| 午夜精品国产更新| 亚洲精品在线看| 蜜桃视频一区| 国语自产精品视频在线看一大j8 | 亚洲精品女av网站| 久久久久久精| 久久精品国产91精品亚洲| 国产精品区一区二区三区| 亚洲最新色图| 99国产精品久久久久久久久久 | 久久综合五月| 影音先锋另类| 免费观看一区| 欧美成人中文| 一区二区动漫| 在线亚洲精品福利网址导航| 国产精品美女久久久久久久| 亚洲特级毛片| 久久蜜桃香蕉精品一区二区三区| 久久视频在线免费观看| 亚洲福利久久| 亚洲一区二区三区四区中文| 亚洲性感美女99在线| 亚洲一区视频在线| 亚洲人成77777在线观看网| 久久gogo国模裸体人体| 在线综合亚洲| 狂野欧美一区| 久久综合久久久久88| 久久久久国产精品麻豆ai换脸| 欧美激情视频在线播放| 亚洲精品在线视频| 欧美一区二区免费观在线| 久久精品二区亚洲w码| 亚洲欧美国内爽妇网| 国产噜噜噜噜噜久久久久久久久| 欧美中文在线视频| 日韩亚洲欧美高清| 老司机aⅴ在线精品导航| 欧美视频一区二区三区在线观看| 伊人蜜桃色噜噜激情综合| 亚洲免费不卡| 久久天天躁狠狠躁夜夜爽蜜月| 久久人体大胆视频| 亚洲免费影视| 欧美α欧美αv大片| 久久理论片午夜琪琪电影网| 日韩视频在线一区二区三区| 亚洲女同同性videoxma| 西西人体一区二区| 国产精品一区二区在线观看网站| 亚洲国产精品久久久久秋霞不卡| 午夜日韩在线| 欧美日韩视频专区在线播放| 国产欧美日韩三级| 亚洲人体一区| 亚洲视频中文| 久久综合狠狠| 欧美日韩在线亚洲一区蜜芽| 亚洲精品综合精品自拍| 夜夜嗨av一区二区三区网页| 国产精品制服诱惑| 免费日韩精品中文字幕视频在线| 欧美喷潮久久久xxxxx| 亚洲线精品一区二区三区八戒| 午夜伦欧美伦电影理论片| 国产偷自视频区视频一区二区| 欧美专区福利在线| 免费亚洲一区| 久久免费视频一区| 国产日产欧产精品推荐色| 欧美激情在线狂野欧美精品| 欧美日韩国产综合久久| 亚洲三级影片| 宅男噜噜噜66一区二区| 欧美精品videossex性护士| 日韩视频不卡| 欧美黑人一区二区三区| 久久精品中文字幕免费mv| 亚洲高清色综合| 欧美在线播放视频| 欧美一区二区三区在线免费观看| 欧美电影资源| 久久久精品日韩欧美| 亚洲理论在线观看| 99精品欧美一区二区三区| 久久一区二区三区四区| 亚洲第一精品夜夜躁人人躁| 欧美国产日韩二区| 久色成人在线| 欧美国产日韩二区| 久久久久国产一区二区| 欧美四级电影网站| 亚洲欧美日韩电影| 久久综合免费视频影院| 日韩视频不卡中文| 国产精品久久夜| 午夜在线视频观看日韩17c| 久久伊人亚洲| 亚洲天天影视| 在线观看精品视频| 欧美成年人视频网站| 亚洲欧美综合国产精品一区| 亚洲精选久久| 中日韩美女免费视频网站在线观看| 精品av久久久久电影| 精品动漫3d一区二区三区免费版 | 亚洲精品黄网在线观看| 亚洲国产精品传媒在线观看| 黄色成人小视频| 亚洲国产美女精品久久久久∴| 亚洲电影免费观看高清完整版在线观看| 国产欧美精品xxxx另类| 国产一区自拍视频| 伊人久久婷婷色综合98网| 亚洲激情综合| 亚洲欧美日韩国产综合精品二区| 亚洲欧美日韩综合国产aⅴ| 久久国产精品一区二区三区| 久久婷婷国产综合精品青草| 欧美激情一区二区三区全黄| 91久久中文| 欧美一区二区三区久久精品| 免费看的黄色欧美网站| 国产精品第13页| 最新国产成人av网站网址麻豆| 亚洲天堂免费在线观看视频| 久久久精品五月天|