c++ - 为什么这个模板示例代码没有编译?

标签 c++ templates lnk2019

<分区>

我正在尝试制作一个使用模板的示例,以便学习如何使用它们。我在 Visual Studio 2010 C++ 中创建了一个包含三个文件的项目:

Controller .cpp:

#include <iostream>

#include "Foo.h"

using namespace std;

int main(){

    Example<int,string> example;

    example.appols(5, "Hi");

    return 0;
}

Foo.h:

#include <iostream> 

using namespace std;

template <class T, class E>
class Foo{
public:
    void printThis(T t, E e);
};

template <class T, class E>
class Example{
public:
    void appols(T t, E e);
};

Foo.ipp:

#include <iostream>

#include "Foo.h"

using namespace std;

template<class T, class E>
void Foo<T, E>::printThis(T t, E e){
    cout << "FOO! " << t << ' ' << e << endl;
}

template<class T, class E>
void Example<T, E>::appols(T t, E e){
    cout << "APPOLS!! " << t << ' ' << e << endl;
    Foo<T,E> f;
    f.printThis(t,e);
}

当我尝试编译时,我得到:

1>------ Build started: Project: Template Practive, Configuration: Debug Win32 ------
1>Controller.obj : error LNK2019: unresolved external symbol "public: void __thiscall Example<int,class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> > >::appols(int,class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> >)" (?appols@?$Example@HV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@@@QAEXHV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@@Z) referenced in function _main
1>C:\Users\Matthew\documents\visual studio 2010\Projects\Template Practive\Debug\Template Practive.exe : fatal error LNK1120: 1 unresolved externals
========== Build: 0 succeeded, 1 failed, 0 up-to-date, 0 skipped ==========

你能帮我看看我在这里做错了什么以及 error LNK2019 是从哪里来的吗? 提前致谢!

最佳答案

破译错误信息

让我们先尝试解码错误消息:

1>Controller.obj : error LNK2019: unresolved external symbol 
"public: void __thiscall Example<int,class std::basic_string<char,struct
std::char_traits<char>,class std::allocator<char> > >::appols(int,class
std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> >)"
(?appols@?$Example@HV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@@@QAEXHV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@@Z) 
referenced in function _main

我们可以开始降低此错误消息中的噪声/信号比。

(?appols@?$Example@HV?$basic_string@DU?$char_traits@D@std@@...的部分只是 C++ 名称修改。它是为 C++ 编译器设计的,并不是人类可读的。所以我们可以直接丢弃它。

简化的错误信息变成:

1>Controller.obj : error LNK2019: unresolved external symbol 
"public: void __thiscall Example<int,class std::basic_string<char,struct
std::char_traits<char>,class std::allocator<char> > >::appols(int,class
std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> >)"
referenced in function _main

第一行告诉我们有一个“未解析的外部符号”。让我们试着识别它,看看接下来的几行。

部分:

class std::basic_string<char,struct std::char_traits<char>...

只是std::string的长名(对应于 std::basic_string 模板,其中 char 作为字符类型并使用默认 char 特征和默认分配器)。

因此,我们可以进一步降低噪声,用 std::string 代替而不是那些冗长的部分:

1>Controller.obj : error LNK2019: unresolved external symbol 
"public: void __thiscall Example<int,string>::appols(int,string)"
referenced in function _main

现在错误更清楚了。

__thiscall部分只是 C++ 成员函数默认使用的调用约定。

所以,链接器提示这个方法:

"public: void Example<int,string>::appols(int,string)"

对应于您的 Example<T,E>::appols() :

template <class T, class E>
class Example{
public:
    void appols(T t, E e);
};

T=intE=std::string .

这对应于您的 main() 中的内容Controller.cpp 中的函数:

Example<int,string> example;

example.appols(5, "Hi");

问题诊断及解决方案

问题是所有模板源代码必须在头文件中,而不是在.cpp 文件中。

事实上,编译器需要模板代码的定义才能实例化它。

因此,您可以将代码从 Foo.ipp 文件移动到 Foo.h(或只是从 Foo.h 移动 #include "Foo.ipp"),并添加 inline到模板函数定义:

// New code in Foo.h

template<class T, class E>
inline void Foo<T, E>::printThis(T t, E e){
    cout << "FOO! " << t << ' ' << e << endl;
}

template<class T, class E>
inline void Example<T, E>::appols(T t, E e){
    cout << "APPOLS!! " << t << ' ' << e << endl;
    Foo<T,E> f;
    f.printThis(t,e);
}

另请注意 using namespace std;在头文件中确实很糟糕,因为这会污染包含您的头文件的所有客户端的全局命名空间。只需使用 std::在头文件中明确添加前缀(例如:std::coutstd::endl 等)。

关于c++ - 为什么这个模板示例代码没有编译?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23088968/

相关文章:

c++ - LLVM 源代码中计算数组长度的函数

C++基础模板题

c++ - Qt with OpenSSL (Windows) 中的编译错误 LNK2019

c++ - SOIL 未解析的外部符号

C++ LNK2019 未解析的外部符号

C++:对函数的 undefined reference ,参数似乎已更改

c++ - 根据 C++ 标准在宏定义中推送/弹出宏时的行为是什么

c++ - 在循环中重置循环

WPF/XAML 在具有数据绑定(bind)和高级模板的 TreeView 中使用 TreeViewItems

c++ - 删除 vector 中的字符串