C++头文件的重定义问题以及头文件互相包含问题
2016-03-10 16:04
381 查看
在C++的头文件里,通常通过 #pragma once与#ifndef两种防止头文件二次编译。
有的人将重复编译,重复包含与重复定义弄混,比如:定义一个类,在实例化它之前并不产生内存开销;这与基本类型有所区别。
明明在头文件使用了#pragma once;#ifndef...#define...#endif,为什么在头文件定义了一个全局变量,还会出现重复定义的错误,为什么头文件里的类的定义却不会报错?
首先:
#pragma
once;#ifndef...#define...#endif这个只能解决重复包含,防止该头文件在一个.cpp文件里二次包含或者二次编译,但无法解决重复定义的
重复包含是编译期间的------------------------------------------------------
重复定义是链接期间的------------------------------------------------------
解决头文件相互包含的问题---超前引用:是解决包含了一次不能包含第二次的问题,头文件互相包含只能编译一次的问题。
类A和类B需要彼此互相引用,这样必然有一个类会先被编译,而另外一个类后被编译,这样在先被编译的类引用后被编译的类的时候,就导致了所谓的超前引用。(就需要在先编译的类文件里声明后编译文件的类。)
1)、使用类声明 在超前引用一个类之前,首先用一个特殊的语句说明该标识符是一个类名,即将被超前引用。其使用方法是:
a) 用class ClassB;声明即将超前引用的类名
b) 定义class ClassA
c) 定义class ClassB;
d) 编制两个类的实现代码。
ClassA和ClassB分别有自己的头文件和cpp文件,这种方法需要演变成:
a) 分别定义ClassA和ClassB,并在cpp文件中实现之
b) 在两个头文件的开头分别用class ClassB;和class ClassA;声明对方
c) 在两个cpp文件中分别包含另外一个类的头文件
NOTE:这种方法切记不可使用类名来定义变量和函数的变量参数,只可用来定义引用或者指针。
2)、使用全局变量
由于全局变量可以避免超前引用,不用赘述。我的习惯是,把类对象的extern语句加在该类头文件的最后,大家喜欢
怎样写那都没有什么大问题,关键是保证不要在头文件中胡乱包含。
3)、使用基类指针。
这种方法是在引用超前引用类的地方一律用基类指针。而一般情况下,两个互相引用的类并不涉及其基类,因此不会造成超前引用。比如:在CMyDialog类中用CView*代替CMyView*,在CMyView类中用CDialog*代替CMyDialog*,这样必然不会造成超前引用。(CMyDialog继承CDialog,CMyView继承CView)。
http://blog.csdn.net/u010177010/article/details/50816994)
全局变量还是会重复定义的。但是对于类而言,定义一个类(属于类型定义),在类的实例化之前,并没有产生内存的开销,与基本类型的定义有所区别。
声明:(可以放在头文件)没有开辟内存的定义,类型定义,比如类的定义,结构体的定义,它是定义一个数据类型而已;
定义:(不可放在头文件)开辟了内存的定义,数据定义,比如类对象定义,变量定义。
一般来说:
不分配内存的,放在头文件
分配内存的放在cpp文件,防止重复定义,当然也要看变量的连接性,内部连接性的可以放在头文件定义。
http://blog.csdn.net/u010177010/article/details/50816994
有的人将重复编译,重复包含与重复定义弄混,比如:定义一个类,在实例化它之前并不产生内存开销;这与基本类型有所区别。
明明在头文件使用了#pragma once;#ifndef...#define...#endif,为什么在头文件定义了一个全局变量,还会出现重复定义的错误,为什么头文件里的类的定义却不会报错?
首先:
#pragma
once;#ifndef...#define...#endif这个只能解决重复包含,防止该头文件在一个.cpp文件里二次包含或者二次编译,但无法解决重复定义的
重复包含是编译期间的------------------------------------------------------
重复定义是链接期间的------------------------------------------------------
解决头文件相互包含的问题---超前引用:是解决包含了一次不能包含第二次的问题,头文件互相包含只能编译一次的问题。
类A和类B需要彼此互相引用,这样必然有一个类会先被编译,而另外一个类后被编译,这样在先被编译的类引用后被编译的类的时候,就导致了所谓的超前引用。(就需要在先编译的类文件里声明后编译文件的类。)
1)、使用类声明 在超前引用一个类之前,首先用一个特殊的语句说明该标识符是一个类名,即将被超前引用。其使用方法是:
a) 用class ClassB;声明即将超前引用的类名
b) 定义class ClassA
c) 定义class ClassB;
d) 编制两个类的实现代码。
ClassA和ClassB分别有自己的头文件和cpp文件,这种方法需要演变成:
a) 分别定义ClassA和ClassB,并在cpp文件中实现之
b) 在两个头文件的开头分别用class ClassB;和class ClassA;声明对方
c) 在两个cpp文件中分别包含另外一个类的头文件
NOTE:这种方法切记不可使用类名来定义变量和函数的变量参数,只可用来定义引用或者指针。
2)、使用全局变量
由于全局变量可以避免超前引用,不用赘述。我的习惯是,把类对象的extern语句加在该类头文件的最后,大家喜欢
怎样写那都没有什么大问题,关键是保证不要在头文件中胡乱包含。
3)、使用基类指针。
这种方法是在引用超前引用类的地方一律用基类指针。而一般情况下,两个互相引用的类并不涉及其基类,因此不会造成超前引用。比如:在CMyDialog类中用CView*代替CMyView*,在CMyView类中用CDialog*代替CMyDialog*,这样必然不会造成超前引用。(CMyDialog继承CDialog,CMyView继承CView)。
http://blog.csdn.net/u010177010/article/details/50816994)
全局变量还是会重复定义的。但是对于类而言,定义一个类(属于类型定义),在类的实例化之前,并没有产生内存的开销,与基本类型的定义有所区别。
声明:(可以放在头文件)没有开辟内存的定义,类型定义,比如类的定义,结构体的定义,它是定义一个数据类型而已;
定义:(不可放在头文件)开辟了内存的定义,数据定义,比如类对象定义,变量定义。
一般来说:
不分配内存的,放在头文件
分配内存的放在cpp文件,防止重复定义,当然也要看变量的连接性,内部连接性的可以放在头文件定义。
http://blog.csdn.net/u010177010/article/details/50816994
相关文章推荐
- C++ 和 C# 开发类型对应信息
- C语言笔记之关键字(一)
- c++ 桥接模式
- C++类虚函数表
- C++中引用、指针,传值的联系和区别
- 二分法查找的C++实现
- PHP中调用C/C++制作的动态链接库的教程
- 5.C语言之函数
- 我们编程吧 之 C++学习手册v0.1
- C++stringstream的clear()清空误区
- c++静态函数
- SYDZ 辗转相除法的原理与实现
- LeetCode: Find Peak Element
- C++近期常见问题面试总结(一)
- C++构造函数和析构函数的总结
- c++ 单例模式
- 高精度运算
- 常用工具类之C++线程安全集合类
- Concurrency::task(C++)
- c++第一次上机报告