模板基类的静态成员不会导出到共享库
Static member of template base class doesn't get exported to shared library
我有一个类"ModelManager",它派生自模板类"TModelManager"。他们的声明如下:
template<class TModel,class TModelMesh,class TModelSubMesh>
class TModelManager
{
protected:
static std::map<std::string,ModelHandle> m_models;
static std::vector<std::map<std::string,ModelHandle>::iterator> m_marked;
[...]
};
class DLLNETWORK ModelManager
: public TModelManager<Model,ModelMesh,ModelSubMesh>
{
[...]
};
有两个共享库,"共享"answers"服务器"。
在"共享"库中,DLLNETWORK相当于linux系统上的'__attribute__((可见性("默认"))',用于导出类。模板类的成员定义如下(在cpp文件中):
template<class TModel,class TModelMesh,class TModelSubMesh>
DLLNETWORK std::map<std::string,ModelHandle> TModelManager<TModel,TModelMesh,TModelSubMesh>::m_models;
template<class TModel,class TModelMesh,class TModelSubMesh>
DLLNETWORK std::vector<std::map<std::string,ModelHandle>::iterator> TModelManager<TModel,TModelMesh,TModelSubMesh>::m_marked;
在"服务器"库中,DLLNETWORK是一个空定义,以确保类已导入。"服务器"-库与"共享"-库链接。
这是一个很好的编译。
在运行时,"服务器"库被动态加载,这也会导致"共享"库被加载。然而,这会导致以下错误:
Unable to load library 'lib/libserver_x64.so': lib/libserver_x64.so: undefined symbol: _ZN13TModelManagerI5Model9ModelMesh12ModelSubMeshE8m_markedE
我在"服务器"-库上使用了"ldd"实用程序,它确认它与"共享"-库链接,并且它可以找到它
然后,我使用"nm"实用程序来查找与TModelManager类相关的所有符号。这就是结果:
nm -D libshared_x64.so | grep ModelManager
0000000000b15610 u _ZGVN13TModelManagerI5Model9ModelMesh12ModelSubMeshE8m_modelsE
000000000072d1b0 T _ZN12ModelManager21CreateFromBrushMeshesERSt6vectorIP9BrushMeshSaIS2_EE
000000000072d10c T _ZN12ModelManager4LoadESs
000000000072d950 W _ZN13TModelManagerI5Model9ModelMesh12ModelSubMeshE21CreateFromBrushMeshesERSt6vectorIP9BrushMeshSaIS6_EE
000000000072d62c W _ZN13TModelManagerI5Model9ModelMesh12ModelSubMeshE4LoadESsPFP8MaterialPKcE
0000000000b155e0 u _ZN13TModelManagerI5Model9ModelMesh12ModelSubMeshE8m_modelsE
除了"m_marked"成员之外,所有的东西都在那里。两次发现"m_models"成员的地址不同。
我真的一点都不明白,"m_marked"-成员的定义方式与"m_models"-成员相同,为什么不导出它?为什么"m_models"成员出现两次?
//编辑:
我没有注意到"m_models"的nm结果前面的"U",这意味着它们是未定义的。
我对它们的定义有问题吗?
模板类的成员定义如下(在cpp文件中):
您似乎假设这些定义将在cpp文件中实例化,但除非该cpp文件的某个部分使用它们,否则成员将不会被实例化,因此相应的符号将不会在编译的对象文件中发出。
服务器库中使用这些静态成员的代码不能隐式实例化它们,因为您已经在cpp文件中隐藏了这些定义。
静态成员定义要么需要为您正在使用的所有专门化显式实例化,要么需要将这些定义放在头中。
- std::具有相同基类的类的变体
- Linux c++.在预加载的共享库中定义的基类的崩溃调用函数
- 从基类的共享指针向下转换到派生类的引用
- C++:在共享对象中调用抽象基类构造函数/未定义的符号
- 派生类实例共享同一基类实例
- 当父类共享指针为返回类型时返回新的基类
- 仅通过基类"create"方法将对象创建为共享指针
- 限制C++中虚拟基类的对象共享
- 模板基类的静态成员不会导出到共享库
- C++让两个子类共享基类中的一个变量
- 如何使用共享基类重载派生类的运算符<<?
- 覆盖基类的虚函数,这些基类不共享公共接口
- 可以共享间接基类的基类实例
- 如何让一组不同的子类对象从另一组共享基类的一个静态变量
- 按值传递共享指针并接受作为基类参数是如何工作的
- 将共享指针的派生类切换到基类
- 智能指针——通过模板传递派生类的共享指针到基类
- 如何在C++中的基类和派生类之间共享一个通用的默认参数值
- 设计模式-如何在C++中组合共享同一基类的两个类
- Polymoprhism - 基类私有成员的子类共享