Link 子类化字符串时出错
Link error when subclassing string
出于各种原因,我将 std::string 子类化为:
class CotengString : public string
{
public:
// Constructors
CotengString();
CotengString(const char* ch) : string(ch) {}
CotengString(const string& str) : string(str) {}
virtual ~CotengString() {};
//Operator"="
CotengString& operator=(const string& str) { return (CotengString&)this->assign(str); }
CotengString& operator=(const char* ch) { return (CotengString&)this->assign(ch); }
};
在 DLL 中,我希望使用这段代码全部编译正确。但是在我的 Google 测试项目中,切换到子类字符串
后出现此错误
LNK2005 "public: __thiscall std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> >::basic_string<char,struct std::char_traits<char>,class std::allocator<char> >(char const *,unsigned int)" (??0?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@QAE@PBDI@Z) already defined in gtest.lib(gtest-all.obj) Devices.Spectro.CppTest <path>\Devices.Spectro.CppTest\Devices.Spectro.Cpp.lib(Devices.Spectro.Cpp.dll)
我的直觉是我遗漏了一些明显的东西。但我不知道它可能是什么
好的,那就作为回答。
第一因
在我看来,这是一个包含多个头文件的问题。
这导致编译器想要再次编译函数或在这种情况下分配器并检测到 "oh I already compiled that!".
因此修复方法是将此添加到头文件中:
#ifndef CUSTOM_STRING_IMPLEMENTATION_HEADER
#define CUSTOM_STRING_IMPLEMENTATION_HEADER
....
#endif
第二个原因
但是,如果不是这种情况,可能您正在尝试在使用 已经包含已编译的 class.
根据您的日志文件,我个人认为是第二个原因。据说分配器已经编译在你的库中。
示例:
如果您只使用头文件,则会出现大问题。看这里
Dll代码:
SomeHeaderFile.hpp
class NiceClass{
//Constructor is implemented. That causes several problems now!
NiceClass{
}
...
}
您的应用程序代码(使用 dll):
SomeNiceApplicationCode:
//Linker error now! It's already compiled right into your dll!
#include <SomeHeaderFile.hpp>
int main(){
NiceClass niceClassInstance;
return 0;
}
解决方案:
应用这些更改并为您的 class 创建额外的 cpp 文件。
在您的应用程序文件中只包含头文件。
class CotengString : public string
{
public:
// Constructors
CotengString();
CotengString(const char* ch) : string(ch); //Use cpp file!
CotengString(const string& str) : string(str); //""
virtual ~CotengString(); //""
//Operator"="
CotengString& operator=(const string& str); //Same for this
CotengString& operator=(const char* ch); //""
};
出于各种原因,我将 std::string 子类化为:
class CotengString : public string
{
public:
// Constructors
CotengString();
CotengString(const char* ch) : string(ch) {}
CotengString(const string& str) : string(str) {}
virtual ~CotengString() {};
//Operator"="
CotengString& operator=(const string& str) { return (CotengString&)this->assign(str); }
CotengString& operator=(const char* ch) { return (CotengString&)this->assign(ch); }
};
在 DLL 中,我希望使用这段代码全部编译正确。但是在我的 Google 测试项目中,切换到子类字符串
后出现此错误LNK2005 "public: __thiscall std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> >::basic_string<char,struct std::char_traits<char>,class std::allocator<char> >(char const *,unsigned int)" (??0?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@QAE@PBDI@Z) already defined in gtest.lib(gtest-all.obj) Devices.Spectro.CppTest <path>\Devices.Spectro.CppTest\Devices.Spectro.Cpp.lib(Devices.Spectro.Cpp.dll)
我的直觉是我遗漏了一些明显的东西。但我不知道它可能是什么
好的,那就作为回答。
第一因
在我看来,这是一个包含多个头文件的问题。 这导致编译器想要再次编译函数或在这种情况下分配器并检测到 "oh I already compiled that!".
因此修复方法是将此添加到头文件中:
#ifndef CUSTOM_STRING_IMPLEMENTATION_HEADER
#define CUSTOM_STRING_IMPLEMENTATION_HEADER
....
#endif
第二个原因
但是,如果不是这种情况,可能您正在尝试在使用 已经包含已编译的 class.
根据您的日志文件,我个人认为是第二个原因。据说分配器已经编译在你的库中。
示例:
如果您只使用头文件,则会出现大问题。看这里
Dll代码:
SomeHeaderFile.hpp
class NiceClass{
//Constructor is implemented. That causes several problems now!
NiceClass{
}
...
}
您的应用程序代码(使用 dll):
SomeNiceApplicationCode:
//Linker error now! It's already compiled right into your dll!
#include <SomeHeaderFile.hpp>
int main(){
NiceClass niceClassInstance;
return 0;
}
解决方案:
应用这些更改并为您的 class 创建额外的 cpp 文件。
在您的应用程序文件中只包含头文件。
class CotengString : public string
{
public:
// Constructors
CotengString();
CotengString(const char* ch) : string(ch); //Use cpp file!
CotengString(const string& str) : string(str); //""
virtual ~CotengString(); //""
//Operator"="
CotengString& operator=(const string& str); //Same for this
CotengString& operator=(const char* ch); //""
};