static inline 内部链接外部链接的关系讨论
一个由inline引起的讨论
以下函数定义有问题么:
//function.h
Void hello(){
Printf(“hello,world”);
}
一般人看起来肯定觉得不对,因为我们基本上只把函数定义放在cpp里面,然后定义一个.h声明一下,在使用的地方include 一下这个.h就Ok了。可是为什么要这样做呢?
换句话说,如果我们按上面的方法定义hello(在一个.h里面定义),然后在两个文件a.cpp和b.cpp里面同时include了它,然后我们编译的时候没错,链接的时候告诉我们hello被定义了两次,这是为什么呢?
我们要知道,你include一个文件的时候相当于把那个文件的内容copy到被include的地方了。所以如果我们有两个文件a.cpp和b.cpp,我们都include了那个hello.h,然后编译,就相当于在a.cpp和b.cpp里面都定义了一个hello,然后链接当然出错了。这是问题的本质
然而,如果把hello的前面加一个inline,也就是说,改成
//function.h
Inline Void hello(){
Printf(“hello,world”);
}
然后再定义a.cpp和b.cpp,同时incldue hello.h,编译和链接都能正常。这又是为什么呢?只不过我们加了一个inline而已。
问题是的本质是inline表明一个函数是内部链接对象,所谓内部链接对象。为了说清楚内部链接对象,我不得不讲一个东西。
编译单元:
在C或者CPP里面,一个编译单元指的是一个可以被编译的文件,在C或者CPP里面,只有.C和.CPP才能被编译的,其它的任何扩展名的文件都不能被编译,比如.h就不能被编译。一个可以被编译的文件就是一个编译单元。所谓内部链接对象,指的是一个同样的名字,如果出现在两个编译单元里面,它们却算不同的东西,则是内部链接对象,否则,如果出现在不同的编译单元的同样的名字算同样的东西,同,就是外部链接对象。
上面的问题加了inline之后就解决了是因为inline函数是内部链接对象,不加inline则是外部链接对象。
同样的问题是static,函数加了static的则是内部链接,不加就是外部链接。对于类的定义也一样,如果一个类的一个函数跟类的实体一起定义的,就是内部链接,否则算外部链接。
比如:
//tt.h
#include<iostream>
using namespacestd;
class TT{
public:
TT();
public:
void hello();
};
TT::TT(){
cout<<"TT"<<endl;
}
void TT::hello(){
cout<<"Hello,worle"<<endl;
}
你这样写的话,这个类是完了,只能被include一次,否则链接出错,因为它没有加static,也没加inline,也就是它是外部链接对象了。如果你把它改成
//TT.h
#include<iostream>
using namespacestd;
class TT{
public:
TT(){
cout<<"TT"<<endl;
}
void hello(){
cout<<"Hello,worle"<<endl;
}
};
那么这个类就能被使用了,因为跟类体一起定义的函数就是内部链接对象了。
当然,如果写成前面这样,就涉及到类的名字解析了,关于类的名字解析,我暂时不说,以后有机会再写。