C++ 链接器错误LNK2019
我一直在玩模板函数,并制作了一个小的日志程序。我一直试图将其拆分为头文件/源文件,但我不断收到链接器错误。我知道这很简单,但我想不出来 另外,我在日志头中有一些变量,它们的“合适”位置在哪里?(日志开始、日志结束等) 下面是所有代码 标题C++ 链接器错误LNK2019,c++,C++,我一直在玩模板函数,并制作了一个小的日志程序。我一直试图将其拆分为头文件/源文件,但我不断收到链接器错误。我知道这很简单,但我想不出来 另外,我在日志头中有一些变量,它们的“合适”位置在哪里?(日志开始、日志结束等) 下面是所有代码 标题 #ifndef __moot_logger_hpp__ #define __moot_logger_hpp__ #include <iostream> #include <fstream> #include <string&g
#ifndef __moot_logger_hpp__
#define __moot_logger_hpp__
#include <iostream>
#include <fstream>
#include <string>
using std::ios;
namespace Moot
{
struct Logger
{
Logger();
~Logger() {}
template <class T>
void saveToFile(T type);
template <typename T>
Logger& operator<< (T type);
/*
Logger& operator<< (std::wstring wideStr)
{
saveToFile(Moot::convertWstringToString(wideStr));
return *this;
}
*/
};
/*
namespace {
Logger logStart;
Logger& lStart = logStart;
const char logEnd = '\n';
const char& lEnd = logEnd;
const char logSpace = ' ';
const char& lSpace = logSpace;
}
*/
}
#endif
\ifndef\uuu模拟记录器\uu水电站__
#定义模拟记录器水电站__
#包括
#包括
#包括
使用std::ios;
名称空间模拟
{
结构记录器
{
记录器();
~Logger(){}
样板
无效保存文件(T型);
样板
记录器和运算符< p>您将要阅读C++常见问题解答,
有效地,需要在头文件中定义函数和类模板,而不是.CPP文件。
< p>您将要阅读C++ FAQ Lite问题,
实际上,您需要在头文件中定义函数和类模板,而不是在.cpp文件中。如果要将定义与模板类的声明分开,而不是使用hpp或tpp将定义移动到单独的文件中(文本编辑器并不总是正确处理tpp)如果要从模板类的声明中分割定义,而不是使用hpp或tpp将定义移动到单独的文件中(文本编辑器并不总是正确处理tpp),请在声明文件的末尾为定义文件扩展名和添加include指令声明文件结尾处定义文件的extension和add include指令请注意,以下划线开头的标识符是保留的。您不应该在标题中使用using指令;这样做只会以眼泪结尾。至于“便利变量”如果它们仅在单个源文件中使用,则应将它们放在该源文件中。如果它们在多个源文件中使用,则应将它们放在头文件中,可能是在“详细信息”命名空间中。就个人而言,我不喜欢将全局实例用于记录器;传递指针或引用要干净得多(或智能指针,如果需要)指向记录器,指向进行日志记录的组件(尽管有些人不同意这种观点).@Alexandre:
比这稍微复杂一点。保留是指所有标识符都以下划线开头,后跟大写字母,全局命名空间中的所有标识符都以下划线开头,并且所有标识符的任何位置都有两个连续的下划线。
仍然,而不是记住这些规则,可能更容易避免全部使用下划线(当然,还有不止一个连续的下划线),因此基本上,我同意你的看法。(+1
来自我)re使用James提出的指令(+1
):请注意,以下划线开头的标识符是保留的。您不应该在标题中使用using指令;这样做只会以眼泪结尾。至于“便利变量,”如果它们仅在单个源文件中使用,则应将它们放在该源文件中。如果它们在多个源文件中使用,则应将它们放在头文件中,可能是在“详细信息”命名空间中。就个人而言,我不喜欢将全局实例用于记录器;传递指针或引用要干净得多(或智能指针,如果需要)指向记录器,指向进行日志记录的组件(尽管有些人不同意这种观点).@Alexandre:
比这稍微复杂一点。保留是指所有标识符都以下划线开头,后跟大写字母,全局命名空间中的所有标识符都以下划线开头,并且所有标识符的任何位置都有两个连续的下划线。
仍然,而不是记住这些规则,可能更容易避免完全使用下划线(当然,还有不止一个连续的下划线),因此基本上,我同意你的看法。(+1
来自我。)re使用James提出的指令(+1
):
#include <Moot/logger.hpp>
Moot::Logger::Logger()
{
std::ofstream logfile;
logfile.open ("logfile.txt", ios::trunc);
logfile << "LogFile - most recent at the bottom\n";
logfile << "-----------------------------------\n \n";
logfile.close();
}
template <typename T>
void Moot::Logger::saveToFile(T type)
{
std::ofstream logfile;
logfile.open ("logfile.txt", ios::in | ios::app);
logfile << type;
logfile.close();
}
template <typename T>
Moot::Logger& Moot::Logger::operator<< (T type)
{
saveToFile(type);
return *this;
}
/*
Logger::Logger& operator<< (std::wstring wideStr)
{
saveToFile(Moot::convertWstringToString(wideStr));
return *this;
}
*/
#include <Moot/logger.hpp>
#include <iostream>
int main()
{
std::cout << "hello" << std::endl;
Moot::Logger() << 12;
//Moot::lStart.saveToFile(23);
//Moot::lStart.operator << 13;
return 0;
};