今天看书看到这样一句话:“模板通常具有外部链接,唯一的例外就是前面有static修饰符的名字空间作用域下的函数模板,因此由于外部链接,不能在函数内部定义模板。”
这句话我只能理解static那块。上网以及使用本地ide试验了下,发现c++还真可以在函数内部声明函数,再在函数外部实现函数,示例如下:
#include<iostream>
using namespace std;
void testIn()
{
int add(int, int);
cout<< add(1, 2)<<endl;
}
int add(int num1, int num2)
{
return num1 + num2;
}
int main()
{
testIn();
return 0;
}
会发现程序可以执行,输出结果为:
3
要理解外部链接和内部链接不得不提下c/c++工程的生成方式:
我们都知道,c/c++编译会经过预处理->编译->链接这三个主要的过程。c/c++都是一个一个.cpp文件单独编译的,彼此间直到链接时都不知道其他cpp文件的信息(这里的单独编译的c/cpp文件称为编译单元)。由于大型项目肯定不可能所有代码都写在一个.cpp文件中,各个文件肯定又是会互相依赖的。因此,在编译过程中,编译器会分析当前cpp文件,记录其可以提供给其他cpp的定义以及自己需要其他cpp文件提供的定义。这时就需要外部链接了,可以将外部链接理解为一个标志,它标志现在当前cpp缺少一个定义,但是这个定义不是不存在的,其存在在其他cpp文件中,这样就可以避免编译失败(典型应用是前置声明和extern声明)。最后在链接过程中利用链接器将所有的obj文件进行链接,将每个标志和正式的定义链接在一起,生成最终的可执行文件。
给出内部链接和外部链接的正式定义:
内部链接:如果一个名称对于某个编译单元来说是局部的,在链接的时候其他的编译单元无法链接到它且不会与其他的链接单元中同样的名称相冲突。例如static函数、inline函数等。
外部链接:如果一个名称对于编译单元来说不是局部的,在链接的过程中其他的编译单元可以访问它。例如全局变量和普通函数(普通函数默认为extern)。
哪些实体拥有内部链接:
-
static全局变量,static函数,友元函数定义
-
类的定义
-
内联函数定义
-
Union共同体定义
-
命名空间的const常量定义
-
枚举类型定义
-
所有的声明(有人将其归结为无链接)
哪些实体拥有外部链接:
-
类的非内联函数(包括成员函数和静态类成员函数的定义)
-
类的静态成员变量的定义
-
名字空间或全局的非静态的自由函数,非静态变量,非友元函数的定义。
因此,拥有外部链接的实体如果被声明在头文件并且被多个.cpp文件包含,可能就会出现链接冲突错误,因为每个包含这个拥有外部链接实体的.cpp都会分配空间,当多个编译单元链接的时候,连接器就会面对多个相同的名字,无法正常链接到正确的对象。
参考:
https://blog.csdn.net/isscollege/article/details/73851795
网友评论