我有一个简单的类,可以将其写入文本文件进行记录。它不是模板类,但我想给它一个添加新条目的模板方法。这样,我就不必为带符号的char *,无符号的char *,std :: string等编写单独的方法。
构建时出现未解决的外部符号错误。我研究了问题,并了解到要么必须在头文件中定义模板函数,要么在源文件的定义中使用export关键字。使用export关键字无效,因此我已经在头文件中定义了它,但仍然出现错误。
我正在将Visual Studio 2019与C ++ 17作为语言标准一起使用。Javelin :: Log位于名为“ Javelin”的项目中,该项目创建一个静态库,项目“ Sygdas”具有对其的引用。
Log.hpp
](在标枪项目中)(在Sygdas项目中)#pragma once #include "pch.hpp" #include "Utility.hpp" namespace Javelin { class Log { public: Log(std::string filename); ~Log(); template<typename T> void AddEntry(T entry) { m_file << GetCurrentTime() << " - " << entry << '\n'; } private: std::ofstream m_file; }; }
Globals.hpp
(在Sygdas项目中)#pragma once #include "Javelin.hpp" // includes Log.hpp namespace Sygdas { inline Javelin::Log game_log{ "log.txt" }; }
Application.cpp
#pragma once #include "wxpch.hpp" #include "Application.hpp" #include "Javelin.hpp" // includes Log.hpp #include "Globals.hpp" namespace Sygdas { wxIMPLEMENT_APP(Application); bool Application::OnInit() { game_log.AddEntry("Game Launched"); m_main_frame = new MainFrame(); return true; } }
我得到的错误是:
error LNK2019: unresolved external symbol "class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> > __cdecl Javelin::GetTickCount(void)" (?GetTickCount@Javelin@@YA?AV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@XZ) referenced in function "public: void __cdecl Javelin::Log::AddEntry<char const *>(char const *)" (??$AddEntry@PEBD@Log@Javelin@@QEAAXPEBD@Z)
如果我从Application.cpp中删除game_log.AddEntry("Game Launched");
行,它的构建就很好。
我理解为什么定义必须在头文件中;编译器需要知道模板的定义才能使用模板创建函数。我不明白为什么Application.cpp在Log.hpp中时没有定义,该定义通过Javelin.hpp包含在内。
感谢您的任何帮助。
GetCurrentTime()定义
std::string GetCurrentTime() { time_t now{ time(&now) }; tm calendar{}; localtime_s(&calendar, &now); char time_text[20]{}; strftime(time_text, sizeof(time_text), "%F %T", &calendar); return std::string{ time_text }; }
我有一个简单的类,可以将其写入文本文件进行记录。它不是模板类,但我想给它一个添加新条目的模板方法。这样,我将不必编写单独的方法...
Application.cpp没有为GetCurrentTime()定义。