【C++】你真的会用#include吗?
来源:互联网 发布:sql instr函数 编辑:程序博客网 时间:2024/06/06 01:59
【C++】你真的会用#include吗?
相信每个C++程序员都有这样的经历:在一个大工程中不知道是否需要#include某个头文件,又或者干脆在每一个头文件中都写上#pragma once或者使用#ifndef <标识> +#define <标识>+ #endif 三板斧。
或许你已经发现了,C++中的#include不同于其他语言(如Java和Python的import),它并不那么友善,稍不留意就会导致编译错误。其实不仅如此,如果对于大工程,随意使用include将会无声无息地一点点拖慢程序的编译速度。
关于使用#include的目的
在头文件中声明函数或者类,然后在对应的cpp文件中写对应的实现,这显然是C++编程的”潜规则”。这时候,应该会有人跳出来说,“不这样也行啊,而且会更方便。”甚至有些“高手”说,这个#include能做的事可多了,比如用来加载配置表。
//setting.hint a = 5;int b = 6;
//main.cpp#include <iostream>using namespace::std;int wow(){ #include "test.h" return a + b;}int main(){ std::cout<<wow()<<std::endl;}
程序的运行结果是11,可能你会相当惊讶。但如果你已经知道#include其实不过是将指定文件内容展开,然后再编译而已,那肯定能轻松理解这个“赢巧奇技”。当然如果是导入配置或者宏一般不会这么做,而应该是在文件开头#include。
因此我们使用#include,一般是一下两个目的:
- 导入typedef,#define,const变量等宏配置;
- 使用在别的cpp文件中定义或者静态库定义的函数或者类。
include雷区:在头文件中定义并实现了函数
阅读以下程序代码:
//test.hint func(){ return 0;}
//test2.h#include "test.h"int func2(){ return func() + 1;}
//main.cpp#include <iostream>#include "test.h"#include "test2.h"using namespace::std;int main(){ std::cout<<func()<<std::endl; std::cout<<func2()<<std::endl; return 0;}
当你点运行的时候,你很可能会惊讶地看到以下的文字:
test/test.h:1: error: redefinition of ‘int func()’
为什么会变成这样呢?(打死白学家)其实很简单,在编译器看来,上面的代码其实等同于下面的:
//FuncA.hint FuncA(){ return 100;}
//main.cpp#include <iostream>int func()// ←由#include "test.h"展开得到{ return 0;}int func()// ←由#include "test2.h"展开得到,而test2.h中又有一个#include "test.h",再次展开得到{ return 0;}#include "test.h"// ←由#include "test2.h"展开得到int func2(){ return func() + 1;}using namespace::std;int main(){ std::cout<<func()<<std::endl; std::cout<<func2()<<std::endl; return 0;}
这样,错误原因就很明显了吧,函数重定义冲突。这再次验证了C++的经典编程规范——“头文件只能声明函数,函数的定义要放到对应的cpp文件中,只能#include该头文件,而不能#include其cpp源文件。”
其实不用#include也行
阅读下面的代码:
//other.cppint func(){ return 5;}
//main.cpp#include <iostream>int func();//←本应该是#include "other.h"int main(){ std::cout<<func(); return 0;}
既然上面说了,include其实不过是将指定文件内容展开,那么我直接像上面那样把本应该出现的#include “other.h”,直接替换为它的内容,不就可以少写一个文件了吗?事实证明也是可行的。如果你是使用图形界面IDE进行编程的,那么你应该理解其背后都干了些什么。实际上IDE偷偷运行了类似下面的命令:
g++ -c other.cppg++ -c main.cppg++ other.o main.o -o test./test
g++的-c选项的含义为仅执行编译操作,而不进行连接操作。当然,我在这里并不是怂恿大家以后就不写#include了,只是让大家明白背后的含义而举个不太恰当的例子,为了少些一个.h头文件而惹来一堆不直观、不方便、难编译的麻烦,这显然是愚蠢至极的做法。
最后给大家看个不使用#include的hello world,其涉及的底层原理,可就不这么容易说明和理解了。
extern "C" { int printf(const char * _Format, ...);}int main(){ printf("hello word"); return 0;}
- 【C++】你真的会用#include吗?
- 你真的会用GOOGLE吗
- 你真的会用 const 吗?
- 你真的会用搜索引擎吗?
- 你真的会用ListView吗?
- 你真的会用StringBuffer吗?
- 你真的会用OneNote吗?
- 你真的会用 CocoaPods 吗?
- 你真的会用Google搜索引擎吗
- 你真的会用Google搜索引擎吗
- 你真的会用Google搜索引擎吗
- 你真的会用Google搜索引擎吗(二)
- UpdatePanel控件,你真的会用了吗?
- NSTimer你真的会用了吗
- NSTimer你真的会用了吗
- NSTimer你真的会用了吗
- NSTimer你真的会用了吗
- Eclipse快捷键,你真的会用了吗?
- CentOs简单命令
- 使用Chrome调试模式获取App混合应用H5界面元素
- Linux中sed命令整理
- 淘淘商城第九天
- 2017西安邀请赛总结
- 【C++】你真的会用#include吗?
- C++学习整理(顺序容器)
- 单链表的反转
- 将两个列表组合成一个字典、join()函数
- 淘淘商城第十天
- poj24047-Relatives(欧拉函数)
- python-列表练习程序ver3
- 如何用springcloud找妹纸之12--- 追随"妹纸"步伐,仗剑江湖(Spring Cloud Sleuth)
- Oracle-Spatial空间数据库基础