函数申明对函数模板实例化的屏蔽

Posted 恋喵大鲤鱼

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了函数申明对函数模板实例化的屏蔽相关的知识,希望对你有一定的参考价值。

1.C++函数匹配顺序

C++语言引入模板机制后,函数调用的情形显的比C语言要复杂。当发生一次函数调用时,如果存在多个同名函数,则C++编译器将按照如下的顺序寻找对应的函数定义。
(1)寻找一个参数完全匹配的函数,如果找到了就调用它。
(2)寻找一个函数模板,并根据调用情况进行参数推演,如果推演成功则将其实例化,并调用相应的模板函数。
(3)如果前面两种努力都失败了,则试着低一级的函数匹配方法,如通过类型转换能否达到参数匹配,如果可以,则调用它。

2. 函数申明对函数模板实例化的屏蔽

如果使用了函数申明,可能会造成对函数模板实例化的屏蔽。考察如下程序。

#include <iostream>
using namespace std;

int square(const int&);

template<class T>T square(const T&i){
    return i*i;
}

int main(){
    cout<<square(5)<<endl; //链接时出错
}

在这个程序中,如果没有函数申明int square(const int&),则函数调用square(5)一定会找到函数模板square并将其实例化。但是由于前面那个函数申明的存在,使得编译器认为一定有一个int square(const int&)存在,不启用函数模板的实例化,并尝试寻找该函数的定义,结果该函数并没有定义,就出现了连接时未找到该函数定义的错误。

这种现象,可以把它叫做函数申明对函数模板实例化的屏蔽。其本质是,在发生函数调用的时候,编译器总是优先调用普通函数而不是函数模板。要解决这个问题,可以采取以下三种办法。
(1)去掉函数申明。
(2)显示指明函数模板的类型参数,即显示模板实参调用(显示调用),将函数调用写成:square< int>(5);
(3)将函数申明改为模板申明,即申明template< class T>T square(const T&);这样就会启用函数模板的实例化。这么做,本质上等同于第一条做法,去掉函数申明。

以上是关于函数申明对函数模板实例化的屏蔽的主要内容,如果未能解决你的问题,请参考以下文章

带有 lambda 作为每个实例化的唯一默认参数的模板

类和对象之模板

虚方法virtual详解

泛型编程(模板)

C++初阶模板

”更高级的宏“模板到底是怎么实例化的?