2012-04-11 113 views
2

我试图创建模板工厂类,导出一个创建方法:dllexport'ing静态模板方法

template <typename T> 
class ClassFactory 
{ 
    _declspec(dllexport) static void* Create() 
    { 
     return new T; 
    } 
}; 

class Foobar : ClassFactory<Foobar> 
{ 
    std::string foo; 
}; 

此代码编译就好了,但我没有看到在出口表时什么我看DUMPBIN /出口

下面的代码创建出口的输出()正确:

class ClassFactoryBase 
{ 
    _declspec(dllexport) virtual void* Create() = 0; 
}; 

template <typename T> 
class ClassFactory : ClassFactoryBase 
{ 
    void* Create() 
    { 
     return new T; 
    } 
}; 

class Foobar : ClassFactory<Foobar> 
{ 
    std::string foo; 
}; 

不过,我需要创建()是静态的。为什么样本2有效,而样本1没有?有没有办法导出静态模板方法?

+0

您的编译器不支持模板的外部链接。几乎没有人会支持它的模块。导出无法工作,您必须将模板定义移动到头文件中。 – 2012-04-11 11:00:49

回答

0

无法从DLL中导出模板方法,因为非实例化的模板方法甚至没有编译。你的例子对DLL本身并没有太多的帮助,头文件就是那个让所有的东西都能正常工作的头文件。

+0

我不是在寻找ClassFactory :: Create()被导出。我想要导出ClassFactory :: Create()。我的理解是,该方法应作为Foobar课程的一部分进行编译。我错过了什么吗? – alexlesh 2012-04-11 17:47:10

2

编译器发现Create()函数从未被调用,因此它不会为其生成任何代码。要使它工作,你需要明确实例化你的模板,像这样:

template class ClassFactory<Foobar>; 

只需将此行添加到您的源代码。现在编译器会生成这个函数的代码并导出它。欲了解更多信息,请参阅此MSDN文章 - Explicit Instantiation (C++)

要回答您的其他问题,为什么示例2的作品和示例1没有,让我们仔细看看派生类Foobar。在这个类中有一个虚函数,所以编译器必须生成一个vtable。要填充vtable,编译器需要知道Create()的地址,这是从基类模板隐式实例化的时候。根据要求生成此函数的代码并将其导出到DLL。这就是为什么示例2有效。