• <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>
            OnTheWay2012
            埋葬昨天的我,迎來重生的我!
            posts - 15,  comments - 89,  trackbacks - 0

                    以下的類實現了一些奇怪的功能,也可以說是一些不常用的功能;先不管這些功能到底是否有用,來看看這些類是怎么實現這些功能的也是挺有趣的。
            (1)請設計一個只能在堆上生存的類
                    在C++中對象有三個存儲空間,靜態存儲區、堆、棧。請設計一個類,該類只能在堆上存儲。如果你是第一次看到這種要求,請先別往下看,自己先想一想。想過了嗎?是不是感覺實現這么個類有點困難?呵呵,其實這個問題如果換如下的問題的話可能更容易解答:請簡單說明一下單例模式的實現方法?大家對單例模式一般都不太陌生吧,具體代碼如下:

             

             

             1class CSingle
             2{
             3private:
             4    CSingle() 
             5    {
             6
             7    }

             8
             9    static CSingle *m_pSingle;
            10
            11public:
            12    static CSingle* GetInstance()
            13    {
            14        if (NULL == m_pSingle)
            15        {
            16            m_pSingle = new CSingle;
            17        }

            18
            19        return m_pSingle;
            20    }

            21
            22}
            ;
            23
            24CSingle *CSingle::m_pSingle = NULL;

                    請注意在單例模式中的類CSingle的對象是不是都是在堆上的?是不是感覺好像知道怎么回答最初的問題了?
                    實現只能在堆上生存的類的具體代碼如下:

             1class COnlySurviveOnHeap
             2{
             3private:
             4 COnlySurviveOnHeap() 
             5 {
             6
             7 }

             8
             9 friend COnlySurviveOnHeap* GetInstance();
            10}
            ;
            11
            12COnlySurviveOnHeap* GetInstance()
            13{
            14 return new COnlySurviveOnHeap;
            15}

            16
            17

            測試代碼如下:

            1int main(int argv, char *argc[])
            2{
            3 COnlySurviveOnHeap *pOnlySurviveOnHeap = GetInstance();//right
            4 COnlySurviveOnHeap object;//error
            5
            6 return 0;
            7}

            8

                    是不是感覺很簡單?是不是感覺和單例模式很像?我在網上搜索了一下這個問題的解答,好多人把單例模式的代碼作為一種實現。但是單例模式的這種實現多了一個限制,那就是只能有一個對象,所以感覺不是太符合題意。

            (2)請設計一個只能在棧上生存的類
                    什么樣的類對象是在堆上生存的呢?那就是通過new創建的對象(不考慮使用malloc分配內存后再調用inplace new的這種方式)。是否可以考慮禁止對這個類進行new操作的方法來實現該類的設計呢?答案是當然可以了。
                    具體代碼如下:

             1class COnlySurviveOnStack
             2{
             3private:
             4 void* operator new(size_t) 
             5 {
             6  assert(false);
             7  return NULL;
             8 }

             9}
            ;
            10

            測試代碼如下:

            1int main(int argv, char *argc[])
            2{
            3 COnlySurviveOnStack *pOnlySurviveOnStack = new COnlySurviveOnStack;//error
            4 COnlySurviveOnStack object;//right
            5
            6 return 0;
            7}

            8

             

            (3)請設計一個類該類不能夠作為基類
                    以下的內容是轉載的。向想出這種方法并且寫的這么詳細這么容易懂的大蝦致敬!我只修改了一下排版格式。
                    如果大家熟悉java的話應該知道java中有一種類不能被繼承,那就是final類.這種類有很多用處,尤其是在大的項目中控制類的繼承層次。
            使子類數量不至于爆炸,在使用了多繼承的類層次中這也是防止出現菱形繼承層次結構的一個好辦法,要實現一個不能被繼承的類有很多方法。如何使類不能被繼承的主要的思路就是使子類不能構造父類的部分,這樣子類就沒有辦法實例化整個子類。這樣就限制了子類的繼承。所以我們可以將父類的構造函數聲明成為私有的,但是這樣父類不就不能實例化了嗎?可以添加一個靜態幫助函數來進行構造。雖然這樣很簡陋,但是這的確是一種解決方法。可是如果只有這個方法能夠解決,那么C++實在是太不靈活了.而且這也不值得寫一片文章出來!有沒有辦法解決上面的方法中的那些問題呢?
                    當然有!我們可以利用友員不能被繼承的特性! 
                    首先假設已經有一個類CXX.這是某一個類層次的分支,我們現在要從CXX繼承一個Final子類CParent來,也就是CParent不能夠被繼承.   我們可以充分利用友員不能被繼承的特點,也就是說讓CParent是某一個類的友員和子類,CParent可以構造,但是CParent的子類CChild確不能繼承那個友員特性,所以不能被構造.所以我們引入一個CFinalClassMixin。
                     我們對這個類的功能是這么期望的:    
                     任何類從它繼承都不能被實例化同時這個類本身我們也不希望它被實例化。
                      如何實現這個類那?很簡單!那就是實現一個構造函數和析構函數都是private的類就行了.同時在這類里面將我們的CParent聲明為友員.   代碼如下:    

             1class CFinalClassMixin   
             2{   
             3friend class CParent;   
             4private:   
             5 CFinalClassMixin(){}   
             6 ~CFinalClassMixin(){}   
             7}
            ;   
             8 
             9class CParent : public CXXX   
            10{   
            11public:   
            12 CParent(){}   
            13 ~CParent(){}   
            14}

            15

            它是從CXXX擴展的一個類(注,此時它還是能夠被繼承).現在我們需要它不能被繼承.那么只要將代碼改成    

             

            1class CParent : public CFinalClassMixin,   public CXXX   
            2{   
            3public:   
            4 CParent(){}   
            5 ~CParent(){}   
            6}
            ;  

                   就行了.現在從CParent繼承一個子類試試 。
                  classCChild : public CParent { };    
                  編譯一下代碼試試,發現:竟然沒有作用!!!
                  現在再回想一下我們這么操作的原因,也就是這個方案的原理:那就是讓父類可以訪問Mixin類的構造函數,但是子類不能訪問。現在看看我們的代碼,發現父類是CFinalClassMixin類的友員,可以訪問它的構造函數。因為友員不能繼承,所以CChild不能訪問CFinalClassMixin的構造函數.所以應該不能被實例化。CChild的確不能訪問CFinalClassMixin的構造函數,但是它卻不必調用它!我想這就是問題的原因所在。CChild是通過CParent來構造CFinalClassMixin的,所以這個友員對他并沒有什么用處! 現在問題找到了.要解決很簡單.只要讓CChild必須調用CFinalClassMixin的構造函數就行了,怎么才能達到目的呢? 還記得虛繼承嗎?虛繼承的一個特征就是虛基類的構造函數由最終子類負責構造!所以將CParent從CFinalClassMixin繼承改成從CFinalClassMixin虛繼承就可以了.代碼如下:  

             

            1class CParent : virtual public   CFinalClassMixin, public CXXX   
            2{   
            3public:   
            4 CParent(){}   
            5 CParent(){}   
            6}
            ;  

                    現在試試,行了。但是可能有些人會對多繼承心有余悸!但是我們這里并沒有必要這么擔心!為什么?因為我們的CFinalClassMixin類是純的!pure!   也就是說它根本沒有成員變量!那么我們就根本不用擔心多繼承帶來的最大問題.菱形繼承產生的數據冗余.以及二義性。現在還有個不足!那就是我們不能每次使用這個CFinalClassMixin類就在里面加上對某個類的友員聲明啊!這多麻煩啊!   雖然不是什么大問題,但是我覺的還是要解決,因為我充分信任C++!解決的方法也很簡單!那就是使用模板!具體描述就省略了,給出代碼大家一看就知道了。
                    下面是我得測試程序的完整代碼(其中的CFinalClassmixin已經改成模板)。

             1template<class   T>   
             2class CFinalClassMixin   
             3{   
             4friend T;   
             5private:   
             6 CFinalClassMixin(){}   
             7 ~CFinalClassMixin(){}   
             8}
            ;  
             9 
            10class CXXX   
            11{   
            12public:   
            13 CXXX(){cout << "I am CXXX" << endl;}   
            14 ~CXXX(){}   
            15}
            ;  
            16 
            17class CParent : virtual public   CFinalClassMixin<CParent>public CXXX   
            18{   
            19public:   
            20 CParent(){}   
            21 ~CParent(){}   
            22}
            ;  
            23 
            24class CChild : public CParent{};   
            25int main(int argc, char* argv[])   
            26{   
            27 CParent   a;   //   可以構造   
            28 //CChild   b;   //不能構造   
            29 return   0;   
            30}
               
            31
            32

                    現在只要對不想被繼承的類加入一個CFinalClassMixin混合類做父類就行了。通過限制構造函數,我們就達到了限制繼承的目的。但是這對有些還是個例外,比如全是靜態函數的類.這些類本身就不需要構造。所以我們對它沒有辦法.但是在大多數情況下,一個全是靜態函數的類多少暗示了程序本身的設計可能是需要斟酌的其實這只是Mixin類(混合類)使用的一個小小例子.還有很多其他的用處,比如UnCopiale等等.就不多說了。我想說明的是大家可能對多繼承比較反感。但是過分否定也是得不償失的。現在對多繼承到底應不應該使用還處在爭論階段。我覺得一個方法是否使用得當,關鍵還是在于使用的人。
                    歡迎各位高手批評指正!

            posted on 2010-05-20 19:38 OnTheWay 閱讀(1512) 評論(1)  編輯 收藏 引用 所屬分類: C、C++

            <2010年11月>
            31123456
            78910111213
            14151617181920
            21222324252627
            2829301234
            567891011

            常用鏈接

            留言簿(4)

            隨筆分類

            隨筆檔案

            友情連接

            搜索

            •  

            最新評論

            閱讀排行榜

            評論排行榜

            九九精品99久久久香蕉| 日日狠狠久久偷偷色综合0| 人妻丰满?V无码久久不卡| 国产91色综合久久免费分享| 欧美喷潮久久久XXXXx| 色青青草原桃花久久综合| 伊人久久大香线蕉精品不卡| 欧美国产精品久久高清| 国产精品成人久久久| 中文国产成人精品久久不卡| 无码人妻少妇久久中文字幕蜜桃| 亚洲中文字幕无码久久2020| 亚洲va久久久噜噜噜久久狠狠| 无码人妻精品一区二区三区久久久| 色偷偷偷久久伊人大杳蕉| 久久综合狠狠综合久久| 久久精品国产91久久综合麻豆自制 | 人妻精品久久久久中文字幕69 | 亚洲精品国精品久久99热一| 欧美熟妇另类久久久久久不卡 | 亚洲综合婷婷久久| 午夜精品久久久久久影视777| 欧美久久久久久午夜精品| 久久亚洲精品无码VA大香大香| 天天躁日日躁狠狠久久| 亚洲国产精品久久久久| 久久天天躁狠狠躁夜夜不卡| 亚洲国产精品18久久久久久| 99久久国产免费福利| 狠狠综合久久综合88亚洲| 91精品国产91久久久久福利| 久久久久久噜噜精品免费直播| 中文字幕久久精品无码| 91精品国产91久久久久久蜜臀| 欧美国产成人久久精品| 中文字幕一区二区三区久久网站| 香蕉久久夜色精品国产尤物| 久久国产精品99精品国产987| 欧美国产成人久久精品| 99久久综合国产精品二区| 7777精品久久久大香线蕉|