C++|C++模板笔记八(类模板分文件编写)

问题:

类模板中成员函数的创建时机:调用阶段。
导致分文件编写时链接不到。
解决:
  • 解决方案1:直接包含.cpp源文件。把include "Person.h"变为 include “Person.cpp”。
  • 解决方案2:将声明.h文件和实现.cpp文件写到同一个文件中,并更改后缀名为.hpp,hpp是约定的名称,并不是强制。
示例: 头文件Person.h中代码:
#pragma once #include using namespace std; template class Person { public: Person(T1 name, T2 age); void showPerson(); private: T1 m_Name; T2 m_Age; };

源文件Person.cpp中代码:
#include "Person.h"template Person::Person(T1 name, T2 age) { this->m_Name = name; this->m_Age = age; } template void Person::showPerson() { cout << "姓名:" << this->m_Name << ", 年龄:" << this->m_Age << endl; }

源文件程序入口函数中
#include using namespace std; #include "Person.h"void test01() { Person p("孙悟空", 999); p.showPerson(); }int main() { test01(); system("pause"); return 0; }

错误信息:
C++|C++模板笔记八(类模板分文件编写)
文章图片

LNK2019 无法解析的外部符号 "public: __thiscall Person,class std::allocator >,int>::Person,class std::allocator >,int>(class std::basic_string,class std::allocator >,int)" (??0?$Person@V?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@H@@QAE@V?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@H@Z),函数 "void __cdecl test01(void)" (?test01@@YAXXZ) 中引用了该符号 01模板

LNK2019 无法解析的外部符号 "public: void __thiscall Person,class std::allocator >,int>::showPerson(void)" (?showPerson@?$Person@V?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@H@@QAEXXZ),函数 "void __cdecl test01(void)" (?test01@@YAXXZ) 中引用了该符号

LNK1120 2 个无法解析的外部命令

三个错误如上所示。调用阶段,导致分文件编写时链接不到。
解决方案 上面提到了两种:
解决方案一:直接包含源文件。 第一种将程序入口中的头文件
#include "Person.h"

写成
#include "Person.cpp"

问题得到解决。
类模板中的成员函数创建时机:是在调用时才分配内存。
分析: 我们在程序中写包含头文件Person.h文件,编译中,无法生成成员函数。因为编译器没有见到过,所以编译器也不会去找这两个函数,也不会创建,为其分配内存。所以会报错。链接阶段解析不到。
如果我们在程序中直接包含.cpp文件(#include “Person.cpp”),相当于直接让编译器去看cpp中的代码,编译器见过这些代码,在Person.cpp中,又有包含头文件(#include "Person.h"),那么编译器相当于把所有东西都看了一遍。这样就可以正常调用。
这样的做法很少用,因为很少有直接让人看源码的。所以第二种解决方式,才是常用的。
解决方案二:
分开写,由于创建时机的问题。导致无法链接到。
将声明和实现写到同一个文件中,并更改后缀名为.hpp
将.h和.cpp中的内容写到一起,将后缀名改为.hpp文件。只要写hpp文件,别人一看就知这事类模板。约定俗成。
将Person.cpp的代码直接复制到Person.h文件中,然后将Person.h文件重命名为Person.hpp。
用的时候,在程序中直接引用hpp文件。
#include "Person.hpp"

类模板文件Person.hpp文件内容:
#pragma once #include using namespace std; template class Person { public: Person(T1 name, T2 age); void showPerson(); private: T1 m_Name; T2 m_Age; }; // 类外实现 template Person::Person(T1 name, T2 age) { this->m_Name = name; this->m_Age = age; } template void Person::showPerson() { cout << "姓名:" << this->m_Name << ", 年龄:" << this->m_Age << endl; }

此时程序可以正常执行。
总结: 类模板中的成员函数创建时机是在:调用阶段,导致分文件编写时,无法链接到源文件。
为此两种解决方案:
  • 第一种:直接引用源文件,
  • 第二种:将类模板的声明和实现放在一个文件中,后缀名按照编程规范以.hpp结尾。

【C++|C++模板笔记八(类模板分文件编写)】

    推荐阅读