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;
};