Exern的静态初始化的相依性
Extern修饰的变量在文件外部的另外一个文件里面同样可以使用,用extern修饰的变量存放在静态存储区,为外部链接。
http://zhidao.baidu.com/question/96882132.html
Csdn博客关于extern
http://blog.csdn.net/cameracanon/article/details/4061419
用例子给你示范
// 1.cpp
int x = 10;
// 2.cpp 注意没有包含1.cpp
#include <iostream>
using namespace std;
extern int x;
int main ()
{ cout << x << endl; }
//则输出10
两个文件同在一个项目(project)中,你不包含某个文件(cpp)而可以用它内部定义的变量,(里是.pp不是.h, 因为在.h中定义的数据不能在.cpp中用除非这个.cpp包含这个.h文件)
例:
// 1.h
#include <iostream>
void print()
{
std::cout << "hello!" << std::endl;
}
// 2.cpp
#include <iostream>
using namespace std;
// 以上两句在这个例子中可以不要
extern void print();
int main ()
{
print();
}
就会出错因为1.h中的void print();在不包含它的文件中是不可调用的,即使在声明了extern 也于事无补,如果你将这个例子中的1.h名字换成1.cpp就对了!
从这些可以看出来,extern在这里起的作用是告诉编译器,你这个print()已经在某个.cpp中已经定义了,这里只不过是声明一下有这个东西,然后拿来用一下。定义只能出现一次,声明却可出现多次,也就是说extern声明可在多个文件中用(包括.h)
还有,你还可以屏蔽extern声明,如第二个例子中的第二个.cpp文件可以改成
#include <iostream>
using namespace std;
// 这里以上两句不能省略,因为,这里extern void print();函数已经不起作用了,在这里调用的而是本文件中定义的void print()函数,其中用到了cout,endl;他们来源于std::<iostream>
extern void print();
void print()
{
cout << "world!" << endl;
}
int main ()
{
print();
}
// 输出结果为world!
还有一个extern "C"就不用说了,用这个可以允许C++程序中调用C的函数!
Initializer.h
/**
* 书本:【ThinkingInC++】
* 功能:处理静态初始化的相依性
* 时间:2014年9月19日21:35:32
* 作者:cutter_point
*/
#ifndef INITIALIZER_H_INCLUDED
#define INITIALIZER_H_INCLUDED
#include <iostream>
extern int x; //声明,但不定义
extern int y;
class Initializer
{
static int initCount;
public:
Initializer()
{
std::cout<<"Initializer()"<<std::endl;
if(initCount++ == 0)
{
std::cout<<"performing initialization"<<std::endl;
x=100;
y=200;
}
}
~Initializer()
{
std::cout<<"~Initializer()"<<std::endl;
if(--initCount == 0)
std::cout<<"performing cleanup"<<std::endl;
}
};
static Initializer init;
#endif // INITIALIZER_H_INCLUDED
Dependency1.h
/**
* 书本:【ThinkingInC++】
* 功能:为了解决extern的影响(技巧2)
* 时间:2014年9月19日21:36:11
* 作者:cutter_point
*/
#ifndef DEPENDENCY1_H_INCLUDED
#define DEPENDENCY1_H_INCLUDED
#include <iostream>
class Dependency1
{
bool init;
public:
Dependency1() : init(true)
{
std::cout<<"Dependency1 construction"<<std::endl;
}
void print() const {std::cout<<"Dependency1 init: "<<init<<std::endl;}
};
#endif // DEPENDENCY1_H_INCLUDED
Dependency2.h
/**
* 书本:【ThinkingInC++】
* 功能:解决extern静态初始化的相依性(技巧2)
* 时间:2014年9月19日21:36:46
* 作者:cutter_point
*/
#ifndef DEPENDENCY2_H_INCLUDED
#define DEPENDENCY2_H_INCLUDED
#include "Dependency1.h"
class Dependency2
{
Dependency1 d1;
public:
Dependency2(const Dependency1& dep1) : d1(dep1)
{
std::cout<<"Dependency2 construction "<<std::endl;
print();
}
void print() const {d1.print();}
};
#endif // DEPENDENCY2_H_INCLUDED
Technique2.cpp
/**
* 书本:【ThinkingInC++】
* 功能:解决extern静态初始化的相依性(技巧2)
* 时间:2014年9月19日21:37:22
* 作者:cutter_point
*/
#include "Dependency2.h"
using namespace std;
int separator()
{
cout<<"---------------------"<<endl;
return 1;
}
extern Dependency1 dep1;
Dependency2 dep2(dep1);
Dependency1 dep1;
int x1=separator();
Dependency1 dep1b;
Dependency2 dep2b(dep1b);
int x2=separator();
Dependency1& d1() //当已经把静态的初始化了之后,再调用这个函数就不会再进行初始化了!
{
static Dependency1 dep1;
return dep1;
}
Dependency2& d2() //定义为静态之后,访问这个静态对象的唯一方法就是调用这个函数
{
static Dependency2 dep2(d1());
return dep2;
}
int main()
{
//!Dependency1& dep1=d1(); //这个注释掉,和不注释的差别!!!
cout<<"come on cutter_point"<<endl;
Dependency2& dep2=d2();
cout<<"let`s go cutter_point"<<endl;
return 0;
}
/*
这个的输出结果可以看出来,d1是否已经被初始化了,如果是0没有初始化,顺序反了
否则顺序正确
*/
PS:以后的文章,我尽量在上程序之前把一些基础的知识先贴出来,我查的一些资料贴出来,程序注释我尽量写详细