有很多關於C++模板類的問題,它們包含靜態成員變量以及從動態庫或共享對象中導出它們。但是這個更深入一點:如果有多個共享對象應該怎麼做,每個共享對象都有自己的一組實例,但可能使用來自另一個共享對象的實例?跨多個DLL/DSO的靜態成員的模板類
考慮下面的示例代碼:
/* file: common.h */
#include <stdio.h>
#define PRINT fprintf (stderr, "(template %d) %d -> %d\n", parameter, data, new_data)
template <int parameter>
class SharedClass
{
static int data;
public:
static void Set(int new_data) { PRINT; data = new_data; }
};
template <int parameter>
int SharedClass<parameter>::data = parameter;
/* file: library1.h */
extern template class SharedClass<1>;
void Library1Function();
/* file: library1.cpp */
#include "common.h"
#include "library1.h"
#include "library2.h"
template class SharedClass<1>;
void Library1Function()
{
SharedClass<1>::Set (100);
SharedClass<2>::Set (200);
}
/* file: library2.h */
extern template class SharedClass<2>;
void Library2Function();
/* file: library2.cpp */
#include "common.h"
#include "library1.h"
#include "library2.h"
template class SharedClass<2>;
void Library2Function()
{
SharedClass<1>::Set (1000);
SharedClass<2>::Set (2000);
}
/* file: main.cpp */
#include "common.h"
#include "library1.h"
#include "library2.h"
int main()
{
Library1Function();
Library2Function();
SharedClass<1>::Set (-1);
SharedClass<2>::Set (-2);
}
讓我們再假設,我們建立了兩個庫,並使用GCC的應用程序:
$ g++ -fPIC -fvisibility=default -shared library1.cpp -o lib1.so
$ g++ -fPIC -fvisibility=default -shared library2.cpp -o lib2.so
$ g++ -fvisibility=default main.cpp -o main -Wl,-rpath=. -L. -l1 -l2
然後運行可執行文件,我們會得到以下結果:
$ ./main
(template 1) 1 -> 100
(template 2) 2 -> 200
(template 1) 100 -> 1000
(template 2) 200 -> 2000
(template 1) 1000 -> -1
(template 2) 2000 -> -2
這意味着庫和可執行文件都訪問相同的每個模板靜態存儲。
如果我們運行上的二進制文件「納米-C」,我們會發現每個靜態成員的定義只有一次,在相應的庫:
$ nm -C -A *.so main | grep ::data
lib1.so:0000000000001c30 u SharedClass<1>::data
lib2.so:0000000000001c30 u SharedClass<2>::data
但我有一些問題。
爲什麼,如果我們從兩個頭取出
extern template class ...
,我們會看到,靜態成員在每個二進制,但測試的應用程序將繼續正常工作?$ nm -C -A *.so main | grep ::data lib1.so:0000000000001c90 u SharedClass<1>::data lib1.so:0000000000001c94 u SharedClass<2>::data lib2.so:0000000000001c94 u SharedClass<1>::data lib2.so:0000000000001c90 u SharedClass<2>::data main:0000000000401e48 u SharedClass<1>::data main:0000000000401e4c u SharedClass<2>::data
是否有可能在MSVC下構建它?
或者更具體地說,如何處理__declspec(dllexport)
和__declspec(dllimport)
來使一些實例化出口,還有一些 - 導入?最後:這是一個未定義行爲的例子嗎?
是的,兩種情況下的地址都是相同的。謝謝。 – intelfx