本文共 2255 字,大约阅读时间需要 7 分钟。
啥叫内连接 外连接 我们知道编译的时候(假如编译器是VS),是以源文件cpp文件为单位,编译成一个个的obj文件,然后再通过链接器把不同的obj文件链接起来. 简单的说,如果一些变量或函数的定义是内连接的话,链接器链接的时候就不会拿它们去与obj比较看有重复定义不,一个源文件中的extern声明的变量或函数也不能使用另外一个源文件中的内连接的变量或函数.而如果是外连接的话则需要在不同的obj中比较是否有重定义的.除了做这样的检查外,链接器还会查看通过extern修饰的变量或函数声明在其他obj中的定义. cpp源文件与h头文件关系 我们知道C++支持多种编程范式,可以完全用采用面向过程,不去用类,当然了很少有人这样做,一般是结合面向过程与面向对象. 那假如有一些处在不同源文件中的变量和函数(不是类中的变量成员或成员函数),我们要使用不同源文件中的变量或函数时咋整呢? 在面向对象中我们使用一个个类的时候自然是用头文件引用下就OK.但现在没有类,只是一个个变量和函数,也能用引用头文件吗 ? 这得看情况,有时可以,有时不行.如果头文件中只有外部声明没有任何定义,那引用头文件完全没有问题.如果头文件中有定义的话,如果只被一个cpp文件引用则没问题,如果被多个cpp文件引用就会出现重复定义的错误.(注:编译器是以cpp文件为单位编译,如果某个h头文件没有被引用的话相当于被抛弃不用了.引用头文件时预编译时只是简单的把头文件复制到引用它的cpp文件中.) extern外部声明 假如在有one.cpp和two.cpp两个源文件. //one.cpp中 ---------------------------------------------------#include//two.cpp中 --------------------------------------------------------using namespace std; int number = 123; //number的定义 .或者写成extern number = 123;当有赋值时,实际上extern失去了应有的作用.所以加不加没影响.void Print() {cout<<"hi,i am one.cpp"<
#include在two.cpp中是怎么得到one.cpp中的number的值的呢,由于用extern int number这样声明了下,表明number在其他源文件中有定义,链接器就会帮助去其他源文件中找的. 假如把上面two.cpp中的extern关键字去掉. 编译时不会出错.但链接时出错了,重复定义了.因为one.cpp中已经定义了个number,不能再定义一个相同的了. static 内部连接 上面的例子中我们知道one.cpp和two.cpp中同时写上int number会出错,说重复定义了.但如果这样using namespace std; extern int number;//这就是所谓的外部声明,此处extern不可省.另外此处绝对不能赋值.如果写成extern int number = 88;会报错是重复定义.extern void Print(); //此处extern可以省略.cout<
//one.cpp中static int number = 123; //two.cpp中static int number; //没显式赋值,会默认赋予0此时却不会出错.因为定义变量时默认是外部连接的.而加上关键字static表示是静态变量,是内部连接,链接器不会去看不同cpp编译成的obj文件中有重名的静态变量不. 当用static修饰后就不能再使用extern修饰了.
//one.cpp中static int number = 123;//two.cpp中extern int number;cout<此时会出错,因为extern声明的number找不到定义.因为one.cpp的number用static修饰表明是内连接了. const关键字
//one.cpp中const int number = 123; //two.cpp中const int number = 321;这里达到的效果与static一样,都属于内部连接,所以不会出错.唯一不同的时const表示常量,定义时必须显式赋予值,且赋值后不能再改变它的值. 不过const还有另外一个特性就是可以和extern一起用. 比如在two.cpp中这样写
extern const int number;cout<//正确输出的值是one.cpp中的number值123 inline与static函数也是内部连接的
//one.cpp中void Test() { } //two.cpp中void Test() { }这样编译时会报错,重复定义了.但如果把上面的两个void Test都改成inline void Test() { }或者static void Test() { }则不会出错.//注意这里讲的inline函数指的是全局函数,不是类里面的inline函数. 所以函数跟一般变量差不多.没任何修饰的就默认是外部连接,有static修饰的则是内部连接.另外没有const函数这一说,只有在类中才可以在函数后面加个const来修饰
转载地址:http://pxnab.baihongyu.com/