C++模板笔记八:类模板分文件编写

问题:

类模板中成员函数的创建时机:调用阶段。

导致分文件编写时链接不到。

解决:

  • 解决方案1:直接包含.cpp源文件。把include "Person.h"变为 include “Person.cpp”。
  • 解决方案2:将声明.h文件和实现.cpp文件写到同一个文件中,并更改后缀名为.hpp,hpp是约定的名称,并不是强制。

示例:

头文件Person.h中代码:

#pragma once
#include<iostream>
using namespace std;


template<typename T1, typename T2>
class Person
{
public:
	Person(T1 name, T2 age);
	void showPerson();
private:
	T1 m_Name;
	T2 m_Age;
};

源文件Person.cpp中代码:

#include "Person.h"



template<typename T1, typename T2>
Person<T1, T2>::Person(T1 name, T2 age)
{
	this->m_Name = name;
	this->m_Age = age;
}
template<typename T1, typename T2>
void Person<T1, T2>::showPerson()
{
	cout << "姓名:" << this->m_Name << ", 年龄:" << this->m_Age << endl;
}

源文件程序入口函数中

#include<iostream>
using namespace std;
#include "Person.h"

void test01()
{
	Person<string, int> p("孙悟空", 999);
	p.showPerson();
}


int main()
{
	test01();
	system("pause");
	return 0;
}

错误信息: 

LNK2019	无法解析的外部符号 "public: __thiscall Person<class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> >,int>::Person<class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> >,int>(class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> >,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::basic_string<char,struct std::char_traits<char>,class std::allocator<char> >,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<iostream>
using namespace std;


template<typename T1, typename T2>
class Person
{
public:
	Person(T1 name, T2 age);
	void showPerson();
private:
	T1 m_Name;
	T2 m_Age;
};

// 类外实现
template<typename T1, typename T2>
Person<T1, T2>::Person(T1 name, T2 age)
{
	this->m_Name = name;
	this->m_Age = age;
}
template<typename T1, typename T2>
void Person<T1, T2>::showPerson()
{
	cout << "姓名:" << this->m_Name << ", 年龄:" << this->m_Age << endl;
}

此时程序可以正常执行。



总结:

类模板中的成员函数创建时机是在:调用阶段,导致分文件编写时,无法链接到源文件。

为此两种解决方案:

  • 第一种:直接引用源文件,
  • 第二种:将类模板的声明和实现放在一个文件中,后缀名按照编程规范以.hpp结尾。

  • 6
    点赞
  • 22
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值