• <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>
            SmartPtr
            本博客已搬至:http://www.cnblogs.com/baiyanhuang/
            posts - 29,comments - 176,trackbacks - 0

            By SmartPtr(http://www.shnenglu.com/SmartPtr/)

             

            對于單件模式, 我想大家應該都不陌生,它可以說是GOF23個設計模式中最簡單,最常用的一個模式了。但看似簡單的東西卻不一定好用,我就在使用時遇到了一個問題。

            1 一個簡單的Singleton

            #include<iostream>
            class Singleton
            {
            public:
                
            static  Singleton& GetSingleton()
                {
                    
            static Singleton singleton;
                    
            return singleton;
                }
                
            void Print()
                {
                    std::cout
            <<"Singleton Print\n";
                }
            private:
                Singleton::Singleton()
                {
                    std::cout
            <<"singleton constructor\n";
                }
            };

            這個類提供了一些的功能(函數Print), 并禁止我們創建這個類的對象(構造函數為private), 提供給我們一個靜態函數接口來訪問這個單件對象(GetSingleton),利用靜態變量的特點實現了其單一性。但是, 這個類有問題嗎?
            2 問題所在
            是的,上面這個簡單的類的確存在問題,而且是一個很嚴重的問題,這個問題讓Singleton類完全失去它存在的意義, 因為它不再唯一!
            是的, 當我們只在一個模塊中使用這個類時(比如說,一個exe),這個類是沒有問題的。但是, 一個稍微復雜一點的軟件, 為了開發的便捷,提高復用度,降低耦合性等原因,其難免會被分成好幾個模塊。那么假設講我現在有兩個模塊,一個DLL(singleton.dll), 用來提供一些基礎的功能, 一個EXE(test.exe),用來提供真正的軟件邏輯。 我現在singleton.dll中封裝了一個Print的函數間(用類Singleton實現)并暴露出來。

            singleton.dll

            void Print()
            {
                Singleton::GetSingleton().Print();
            }

            并在test.exe中這樣調用:
            Test.exe

            Singleton::GetSingleton().Print();
            Print();

            這個時候,我們會發現在調用Singleton::GetSingleton().Print()時會產生一個Singleton對象, 而在調用Print()時, 也會產生一個Singleton對象, 也就是說我們有了兩個Singleton實例, singleton不再是singleton。那么,為什么會這樣呢。
            static  Singleton& GetSingleton()
            {
                static Singleton singleton;
                return singleton;
            }

            這個函數應該只會在第一次調用時創建Singleton對象,無論如何, 不應該出現會創建兩次, 調用兩次構造函數的情況。對于靜態變量特性理解沒錯(只在第一次經過時被初始化), 編譯器也沒問題(vc8.0),難道兩次經過該靜態變量是都是第一次? 那么,難道兩次調用的GetSingleton函數并不是同一個函數?讓我們逐一來看:

            1) Singleton::GetSingleton().Print()
            在Test.exe中直接調用該函數,因為包含的頭文件singleton.h有完整的實現, 在鏈接時會在Test.exe保存一份Singleton::GetSingleton()的實現代碼。
            將其標為Singleton::GetSingleton_1();
            2) Print();
            Print()函數是從singleton.dll中導出而來的,而Print()會調用Singleton::GetSingleton(), 在鏈接模塊singleton.dll時,因為其包含的頭文件有完整的實現, 這個DLL也會保存一份Singleton::GetSingleton()的執行代碼。 我將它標為Singleton::GetSingleton_2(), 雖然我們包含的是同一個頭文件,兩個是相同的函數名字, 但是這個函數在兩個不同的模塊中都存有一份獨立的實現。實際上, 他們已經成為兩個不同的函數了。

            看來,兩個函數的確不是同一個函數。

            3 如何解決

            既然知道了原因,就會有相應的解決方法。既然我們知道有兩份獨立的代碼分別存在于兩個模塊中, 那么我們要做的就是讓它只有一份。最好的結果就是這個函數保存在dll中, 在Test.exe不再存有該函數的執行代碼, 而是調用dll中的那個函數。現在結果很明顯了:將Singleton.h編譯鏈接singleton.dll并將外部需要使用的函數暴露出來。這樣,不管有多少模塊使用到singleton, 我們始終執行singleton.dll中的代碼。

            如下:
            SINGLETON_API static Singleton& GetSingleton()
            {
                 static Singleton singleton;
                 return singleton;
            }
            注:
            #ifdef SINGLETON_EXPORTS
            #define SINGLETON_API __declspec(dllexport)
            #else
            #define SINGLETON_API __declspec(dllimport)
            #endif
            這樣在test.exe中使用該函數時,就不會再產生一個副本了,從而保證了我們的應用程序只有一個singleton實例

            posted on 2007-08-28 11:37 SmartPtr 閱讀(1519) 評論(0)  編輯 收藏 引用
            亚洲中文字幕伊人久久无码 | 天天爽天天爽天天片a久久网| 久久人人爽人人爽人人AV| 亚洲精品无码久久一线| 久久精品9988| 亚洲国产综合久久天堂 | 久久久久久综合网天天| 亚洲国产另类久久久精品黑人 | 日本欧美国产精品第一页久久| 亚洲精品99久久久久中文字幕| 无码久久精品国产亚洲Av影片| 国产精品99久久久久久www| 国产免费久久精品99re丫y| 婷婷综合久久狠狠色99h| 久久久这里只有精品加勒比| 99久久99这里只有免费的精品| 日韩AV毛片精品久久久| 久久成人国产精品二三区| 亚洲日韩中文无码久久| 婷婷久久综合| 久久99精品久久久久久野外| 久久精品国产亚洲AV嫖农村妇女 | 久久亚洲AV成人出白浆无码国产| 国内精品免费久久影院| 国产精品毛片久久久久久久| 国产成人精品久久| 伊人情人综合成人久久网小说| 久久精品国产亚洲一区二区三区| 精品久久久久久综合日本| 怡红院日本一道日本久久| 久久男人Av资源网站无码软件 | 久久婷婷国产综合精品 | 久久强奷乱码老熟女网站| 久久久久一级精品亚洲国产成人综合AV区 | 久久亚洲高清观看| 国产韩国精品一区二区三区久久| 亚洲va中文字幕无码久久 | 97精品伊人久久久大香线蕉| 亚洲精品97久久中文字幕无码| 久久久久黑人强伦姧人妻| 久久精品亚洲男人的天堂|