跨dll中使用單例 不要使用模板

2021-07-22 06:59:16 字數 1706 閱讀 7977

c++的模板可以幫助我們編寫適合不同型別的模板類,給**的復用性提供了極大的方便。近來寫了乙個涉及單例的c++模板類,簡化下來可以歸結為以下的**:

1

2

3

4

5

6

7

8

9

10

11

template<typenamet>

classsingleton

};

那麼如果希望對某個work horse類,比如叫做foo,定義乙個singleton,就會很容易啦: 1

foo* foo = singleton::getinstance();

注意這裡不需要自己釋放foo,因為它不是new出來的。

如果**被編譯成「乙個」so(dll)或可執行檔案,這裡的singleton得到的物件卻是是單例的,也就是說,某一種型別得到的物件位址是確定的。

但是,如果同乙個型別的單例在不同的so(dll,可執行檔案)中使用,那麼得到的同乙個型別的單例物件,其位址也是不一樣的。比如

libfoo.so檔案中的如下**:

1

2

foo* foo = singleton::getinstance();

std::type_info footype =typeid(singleton);

和libbar.so中的另一端**: 1

2

3

foo* bar = singleton::getinstance();

std::type_info bartype =typeid(singleton);

其中foo和bar的位址是不同的!他們並不是真正的單例。

為什麼呢?原因是模板是編譯的時候例項化成「真正的類」的,而在兩個不同的so編譯生成的過程中,編譯器進行了兩個不同的例項化過程,他們被例項化成了不同的類。也不是完全不同,但有部分是不同的。

比如,對上述兩個so,如果去測試兩個singleton型別是否為同一型別(rtti):

1

if(footype == bartype)

那麼該測試會返回false。但是,如果測試兩個型別的名字是否相等: 1

if(strcmp(footype.name(), bartype.name()) == 0)

該測試則會返回true。

這說明,兩個型別雖然type_info不同,但名字卻是相同的。

在google上搜了一下相關的資訊,發現這確實是乙個難題。因此,用模板來實現單例,是無法跨so的。當然,這裡不是真正用模板來實現單例,只是用這個例子來演示模板的rtti特性。

設計模式 再嚴謹的單例也盡量不要使用

設計模式學習 注意 大多數的開發者都認同使用全域性可變的狀態是不好的行為。太多狀態使得程式難以理解,難以除錯。不管什麼情況下,我們都應該慎重考慮一下是否必須使用單例。單例應該只用來儲存全域性的狀態,並且不能和任何作用域綁 定。如果這些狀態的作用域比乙個完整的應用程式的生命週期要短,那麼這個狀態就不應...

EXE中使用DLL的模板類

模板類是乙個編譯鏈結期間才例項化的類。只有用到才例項化。標準沒有支援對模板類的匯出,從另外一種意義上來說,模板類的實現全部放在標頭檔案中,也就不需要匯出了。但是對於一些特別情況。模板類中有靜態變數和函式。這個時候dll中使用的,以及和其他鏈結這個dll的模組他們是使用的兩份拷貝。比如,在dll中這樣...

另人厭煩的執行緒安全單例以及不要使用雙檢測

群裡熱烈的討論了執行緒安全的單例 一路從volitile扯到彙編,從 到 真是夠了 首先volitile 跟多執行緒沒直接的關係,或許有些特定情況下會用到 至於spincout之類的實現,內部使用了volitile,這類就不多說了,有興趣的可以自己看實現 千萬別使用下面 不要使用雙檢測,不要使用雙檢...