读《模板的声明和实现为何要放在头文件中?》有感

来源:互联网 发布:完美主义 知乎 编辑:程序博客网 时间:2024/05/22 12:56

先看一个普通类的生成顺序:

//test.h

#ifndef _TEST_ #define _TEST_#include <iostream>#include <string>class Test {public:Test(int m);~Test();void sum(int n);private:int m;};#endif

//test.cpp

#include "test.h"Test::Test(int m){this->m = m;}Test::~Test(){}void Test::sum(int n){std::cout<<m+n<<std::endl;}
//main.cpp

#include "test.h"int main(){ Test t(5);t.sum(3);system("pause");return 0;}
编译器首先编译main.cpp生成main.obj,执行到Test t(5)是,到test.h中查找整个类的定义,由于test.h中全是声明,所以main.obj只能处于监听(我暂且这样思考)。编译test.cpp生成test.obj,通知main.obj的监听,定义已经编译完了,存在定义。main.obj得到定义,连接obj,生成exe。

来看看模板:

//test.h

#ifndef _TEST_ #define _TEST_#include <iostream>#include <string>template<typename T>class Test {public:Test(T m);~Test();void sum(T n);private:T m;};#endif

//test.cpp

#include "test.h"template<typename T>Test<T>::Test(T m){this->m = m;}template<typename T>Test<T>::~Test(){}template<typename T>void Test<T>::sum(T n){std::cout<<m+n<<std::endl;}

//main.cpp

#include "test.h"

#include "test.h"int main(){ Test<int> t(5);t.sum(3);system("pause");return 0;}
编译出错!因为main.obj在test.h没有找到定义之后发起一个监听(我的理解),编译器就去编译test.cpp了。由于在test.cpp中没有模板具现化的代码(没有与Test<int>匹配的定义),也就没有能响应main.obj监听的通知,main.obj就不能实例化Test<int> t(5)这个对象,因为找不到定义。

如果:

#include "test.cpp"int main(){ Test<int> t(5);t.sum(3);system("pause");return 0;}
直接包含test.cpp的话,main.obj就先到test.cpp中查找,这不是一个监听的过程,是一个主动的查找过程,直接匹配带入一下,找到合适定义,就能生成对象了,程序也就能成功执行了。这样有一个缺点,在main.cpp中包含了test.cpp和test.h,内容过大,想想看都不舒服。

为了让main.obj能直接找到Test<int>的定义,那就把Test<T>的声明和定义都放在同一个文件中把。这样比直接包含cpp美观点。

个人思维,可能不严谨。

原文地址:模板的声明和实现为何要放在头文件中?





原创粉丝点击