为什么模板的声明与定义不能分离?
创始人
2024-01-28 00:32:59
0

目录

一、模板的好处与注意事项

二、 声明定义为什么不能不放一起?

一、模板的好处与注意事项

模板的好处从下面代码可以体现:

template
void Swap(T& left, T& right)
{T temp = left;left = right;right = temp;
}
int main()
{int a = 3;int b = 4;Swap(a, b);cout << a << " " << b << endl;double c = 2.4;double d = 3.5;Swap(c, d);cout << c << " " << d << endl;return 0;
}

 

         以上不用写两遍Swap,Swapint与Swapdouble,只需利用模板,然后由编译器进行转换处理即可。

再看一段代码:

template
T Add(const T& left, const T& right)
{return left + right;
}
int main()
{int a1 = 10, a2 = 20;double d1 = 10.0, d2 = 20.0;Add(a1, a2);Add(d1, d2);Add(a1, d2);return 0;
}

注意:

1. typename是用来定义模板参数关键字,也可以使用class(切记:不能使用struct代替class)

2. 对于语句Add(a1, d2);
    该语句不能通过编译,因为在编译期间,当编译器看到该实例化时,需要推演其实参类型
    通过实参a1将T推演为int,通过实参d1将T推演为double类型,但模板参数列表中只有一个T,
    编译器无法确定此处到底该将T确定为int 或者 double类型而报错
    注意:在模板中,编译器一般不会进行类型转换操作,因为一旦转化出问题,编译器就需要背黑锅

    此时有三种处理方式:1. 用户自己来强制转化 2. 使用显式实例化3.使用多个模板参数
    1)   cout << Add(a1, (int)d2) << endl;

     2)  使用显式实例化;cout << Add(a, b) << endl;
     显式实例化:在函数名后的<>中指定模板参数的实际类型

template
T Add(const T& left, const T& right)
{return left + right;
}
int main(void)
{int a = 10;double b = 22.4;// 显式实例化cout << Add(a, b) << endl;//显式实例化:在函数名后的<>中指定模板参数的实际类型return 0;
}

        3)使用多个模板参数

 注意:这样也是无法推导出模板参数类型的,不要想当然的认为能推导出返回值是int*。

template
T* func(int n)
{return new T[n];
}
int main()
{//int* p = func(10);//未能为T推导模板参数double* p = func(10);return 0;
}
/*函数模板的类型一般是编译器根据实参传递给形参,推演出来的
如果不能自动推演,那么我们就需要显示实例化,指定模板参数*/

 对于如下代码需要注意:类模板中函数放在类外进行定义时,需要加模板参数列表

Vector::~Vector()

此外对于类的实例化:

        类模板实例化与函数模板实例化不同,类模板实例化需要在类模板名字后跟<>,然后将实例化的类型放在<>中即可,类模板名字不是真正的类,而实例化的结果才是真正的类。

// Vector类名,Vector才是类型
Vector s1;
Vector s2;

 //动态顺序表//注意:Vector不是具体的类,是编译器根据被实例化的类型生成具体类的模具template
class Vector
{
public:Vector(size_t capacity = 10): _pData(new T[capacity]), _size(0), _capacity(capacity){}// 使用析构函数演示:在类中声明,在类外定义。~Vector();
private:T* _pData;size_t _size;size_t _capacity;
};
template 
Vector::~Vector()
{if (_pData)delete[] _pData;_size = _capacity = 0;
}

 再来看一段代码,当存在专门处理int的函数时

 从上运行结果可以知道他不会去调用模板。

如果显示调用,就会去调用模板。

二、 声明定义为什么不能不放一起?

test.c

#include "template.h"int main() 
{Rect rect(1.1f, 2.2f, 3.3f, 4.4f);rect.display();return 0;
}

 template.h

#pragma once
#include
using namespace std;template
class Rect 
{
public:Rect(T l = 0.0f, T t = 0.0f, T r = 0.0f, T b = 0.0f) :left_(l), top_(t), right_(r), bottom_(b) {}void display();
private:T left_;T top_;T right_;T bottom_;
};

 template.cpp

#include "template.h"
template
void Rect::display()
{std::cout << left_ << " " << top_ << " " << right_<< " " << bottom_ << std::endl;
}

 编译没有错误:

 但是CTRL+f5出错:

         1. 一个C++项目分为若干个cpp文件和h文件,每个cpp文件单独编译成每个的目标文件,最终将每个cpp文件连接在一起组成最后的单一的可执行文件。这里最重要的点就是:编译是相对于每个cpp文件而言的。

        2. 在分离式编译的环境下,编译器编译某一个cpp文件时并不知道另一个cpp文件的存在,也不会去查找(当遇到未决符号时它会寄希望于链接器)

        3. 在没有实例化之前,编译器都是不知道T是什么的。

        3. 类Rect, 其类定义式写在tempalte.h,类的实现体写在template.cpp中。由第一点可以知道template.cpp和test.cpp在编译的时候都要展开template.h,于是在test.cpp中出现了声明,在template.cpp中出现了声明与定义,但是两个cpp是相对独立,从第二点可以知道两个cpp是相对独立的,且由第三点,实例化是在test.cpp中的main函数中实现,在test.cpp中只存在声明,编译是可以通过的,但是在链接的过程中,需要找到Rect的实现部分。我们会说不是在template.cpp的编译的时候,展开了头文件,得到了声明和定义吗?为什么不行了?
        是因为在template.cpp中由于编译器不知道T的实参是什么,并没有对其进行处理。因为cpp是独立编译的,因此,Rect的实现自然并没有被编译,链接也就自然而然地因找不到而出错。

        4. 这种模式在没有模板的情况下运行良好,但遇到模板时就傻眼了,因为模板仅在需要的时候才会实例化出来。所以,当编译器只看到模板的声明时,它不能实例化该模板,只能创建一个具有外部链接的符号并期待链接器能够将符号的地址决议出来。然而当实现该模板的cpp文件中没有用到模板的实例时,编译器懒得去实例化,所以,整个工程中就找不到一行模板实例的二进制代码,于是链接器也黔驴技穷了。

        5. 也就是说,模板如果将类声明和类实现进行分离,那么分离式编译模式会导致在链接的时候出现问题。如下代码就运行通过。

相关内容

热门资讯

新型中小投资项目 5个项目 新... 提起适合穷人的18个创业项目小投资的都有哪些,想必大家都有一定了解,有人问请问现在新型投资项目有哪些...
学生自主创业 学生自主创业 学... 以下是西安领军教育集团董事长吕鹏程在2012腾讯大秦网教育论坛主题演讲:学生自主创业不能说的秘密实录...
一个合适的创业合作伙伴很重要 ... 找到一个合适的创业合作伙伴那样的话,成功率就会大很多,可是要如何才能找到一个好的合作伙伴呢?下面由小...
学生自主创业项目 学生自主创业...   :保健面包房开一家面包店投资不大,对很多人来说是件容易的事。但用传统的烤制方式再加上传统的配料,...
深圳创业项目 深圳创业项目 深... 深圳市一个人杰地灵的地方,南方城市的标杆,很多年轻人都向往的城市,有挑战,更有机会,从数据上看深圳的...
农林致富好项目有哪些 这四个农... 农林致富好项目有哪些?现在大家都有一个思想,尤其是在农村不少人都想自己创业赚钱,因为毕竟在农村创业优...
代理小本创业新开店项目 代理小...   创业开店项目小本创业项目推荐:纺吧,休闲娱乐的新时尚1在城市繁华居民区里或在游乐休闲集聚地租一套...
浙江福建等地积极应对台风“丹娜...   央视网消息(新闻联播):7月7日,中央气象台发布台风蓝色预警。浙江、福建等地加强防范,积极应对将...
怎么创业 怎么创业 怎么创业呢... 一无所有的人怎么创业?分类:创业故事|如何创业|Word文档下载一无所有的人怎么创业?创业,先从认识...
你们是怎么创业的? 你们是怎么... 女朋友在毕业后的第1年内因为忍受不了事业单位的不良风气决定离职。同年,我因为忍受不了所任职私企的不良...