多文件编写类模板编译错误问题

案例

类头文件(Person.h)

#pragma once
template<class T>
class Person
{
public:
	Person(T age);
	void show();
	T age;
};

 类的实现(Person.cpp) 

#include "Person.h"
template<class T>
Person<T>::Person(T age)
{
	this->age = age;
};
template<class T>
void Person<T>:: show()
{
	cout << "Age:" << age << endl;
}

 主函数(test.cpp)

#define _CRT_SECURE_NO_WARNINGS
#include<iostream>
#include"Person.h"
using namespace std;
int main()
{
	Person<int>P(10);
	P.show();
	getchar();
	return 0;
}

  编译结果

 

 原因分析

   1.模板的编译机制 

  模板需要两次编译

  第一次编译是在实例化之前:用来分析基本的语法错误,

  第二次编译是在实例化之后,当把这个类型替换之后,判断有没有语法错误.

  编译器在看到模板的定义的时候。并不马上产生代码,仅仅有在看到用到模板时,比方调用了模板函数 或者 定义了类模板的

  对象的时候。编译器才产生特定类型的代码。进行实例化

   2.c++的编译机制

  C++的编译机制是对每一个cpp文件进行单独编译,在单独编译时如果发现一个函数调用,如果在当前文件找不到函数体,则可能在其他cpp文件中实现了此函数的声明.编译器会在函数位置生成符号代替此函数,在最终的链接阶段由链接器来寻找函数体进行链接

   因此,类模板在编译时,无法知道其他cpp文件中对类模板是否有实例化,因此只进行第一步编译,没有进行实例化,而链接器在链接过程中没有找到实例化的类模板与之对应,因此链接失败,编译错误.

解决方法

  方法一:将主函数中的头文件(.h)改写为(.cpp) 

 

#define _CRT_SECURE_NO_WARNINGS
#include<iostream>
#include"Person.cpp"
using namespace std;
int main()
{
	Person<int>P(10);
	P.show();
	getchar();
	return 0;
}

  方法二:将类模板的声明与定义写入同一文件中,并将(.cpp)改为(.hpp)便于与其他文件作出区别(推荐使用)

template<class T>
class Person
{
public:
	Person(T age);
	void show();
	T age;
};

template<class T>
Person<T>::Person(T age)
{
	this->age = age;
};
template<class T>
void Person<T>:: show()
{
	cout << "Age:" << age << endl;
}
#define _CRT_SECURE_NO_WARNINGS
#include<iostream>
#include"Person.hpp"
using namespace std;
int main()
{
	Person<int>P(10);
	P.show();
	getchar();
	return 0;
}

  

猜你喜欢

转载自www.cnblogs.com/qq209049127/p/10720381.html
今日推荐