覆盖fstream的streambuf

时间:2014-09-24 14:00:04

标签: c++ stl

我正在将非常旧的遗留代码从VS2008移植到VS2013。此代码库的一部分是一个相当复杂的文件记录库,它覆盖了streambuf并将其与fstream相关联。它通过继承streambuf和fstream来实现这一点。

但是当我尝试将生成的DLL与另一个使用它的DLL链接时,我得到:

1>syscored.lib(syscored.dll) : error LNK2005: "public: void __thiscall
std::basic_fstream<char,struct std::char_traits<char> >::close(void)"
(?close@?$basic_fstream@DU?$char_traits@D@std@@@std@@QAEXXZ) already
defined in iptsrvfl.obj 
1>syscored.lib(syscored.dll) : error LNK2005:
"public: void __thiscall std::basic_fstream<char,struct
std::char_traits<char> >::`vbase destructor'(void)"
(??_D?$basic_fstream@DU?$char_traits@D@std@@@std@@QAEXXZ) already
defined in iptsrvfl.obj

基本上,从fstream继承导致DLL导出fstream的一些符号。我使用该DLL的类也使用标准的fstream实例,而close()和dtor()的符号被视为已定义。

我尝试更改fstream派生类以使用包含而不是继承,但是没有办法将自定义streambuf与包含的流相关联。它不是通过公共接口公开的。 (我们在fstream的ctor中调用init(streambuf))。

有人能告诉我: 1)如何将streambuf与包含的fstream,OR相关联 2)如何避免这种符号冲突。

感谢。

2 个答案:

答案 0 :(得分:1)

如果导出的类继承自未显式导出的模板实例化,则编译器会隐式导出此模板实例化。 Source。你不想这样做,因为它会导致你所看到的确切错误。

所以你不应该像你已经完成那样导出你的记录器类。实际上你应该很少导出类。如果您需要在DLL之外提供类的实例,请导出类工厂(函数)。仅当您希望其他人继承该类时才导出类,并且永远不会导出任何类型的模板。您可以导出特定的模板实例。

如果您需要继承标准库模板,并希望其他人继续继承您的类,您可能必须使其成为仅限标题的全内联类,或者可能选择性地导出其方法而不是类本身。

答案 1 :(得分:0)

您可以通过链接到CRT DLL来避免符号冲突。静态链接只有在编译独立的EXE或者不导出任何标准C ++类型的DLL(即纯C接口或COM DLL)时才有意义。