关于与include搭配的符号(双引号 & 尖括号):
C++有一些编写好的头文件(比如标准函数库等等),它们存放在VC++的Include文件夹里。当我们使用#include <文件名>命令时,编译器就到这个文件夹里去找对应的文件。用这种写法去包含一个我们自己编写的头文件(不在那个Include文件夹里)就会出错了。所以包含C++提供的头文件时,应该使用尖括号。
#include "文件名"命令则是先在当前文件所在的目录搜索是否有符合的文件,如果没有再到Include文件夹里去找对应的文件。因此,无论这个文件是C++提供的还是自己编写的,使用#include "文件名"命令一定是正确的。但系统的头文件最好还是用尖括号,那样可以加快搜索速度。
小节:
双引号定义从当前文件目录下进行查找,双尖括号定义从标准库目录开始查找。如果不是自己的头文件,就用尖括号,这样可以加快搜索的速度;如果是自己的头文件,就用双引号。
关于头文件里写的的内容:
头文件是一些以.h作为扩展名的标准文本文件。一般情况下,都应该把自定义的头文件和其余的程序文件放在同一个子目录里,或者在主程序目录下专门创建一个子文件夹来集中存放它们。
可以用头文件来保存程序的任何一段代码,如函数和类的声明,但一定不要用头文件来保存它们的实现。
与标准的C++源代码文件相比,在头文件里应该使用更多的注释。至少把它的用途和用法描述清楚。
应该在注释里说明的内容包括:创建日期、文件用途、创建者姓名、最后一次修改日期、有什么限制和前提条件等等。头文件里的每以一个类和函数也应该有说明。
头文件典型的做法是只用它们来保存函数声明、用户自定义类型数据(结构和类)、模板和全局性的常量。
如果你有一个程序需要多次调用一个或一组函数,或是你有一个或一组函数需要在多个程序里调用,就应该把它们的声明拿出来放到一个头文件里。
头文件应该只包含最必要的代码,比如只声明一个类或只包含一组彼此相关的函数。
小节:
多写些注释,对于类和函数只写声明不写实现。
写的内容->函数声明、用户自定义类型数据(结构和类)、模板和全局性的常量。
内容的用途->多次调用的一个或一组函数、一个或一组函数需要在多个程序里调用。
带目录的头文件:
include时,双引号里,
【.\SRC\】 这样写表示,当前目录中的SRC文件夹,还可以直接写【SRC\】;
【..\SRC\】这样写表示,当前目录的上一层目录中SRC文件夹;
【..\..\SRC\】 这样写表示,当前目录的上两层目录中SRC文件夹;
要是不用上面这种写法,就是在项目属性的附加目录里添加所有需要包含文件的目录。
预处理命令:
预处理用法:
#if FLAG
//代码
//代码
//代码
//代码
#endif
FLAG为0,就不执行里面的代码;要是为1,就执行里面的代码。
这个最大的功能就是用来裁剪功能。
把功能模块放到这个结构里,裁剪时,FLAG置0,则为裁剪;FLAG置1,则为保留。
这个用法一般是在系统裁剪时使用,当看过系统级源码时,就知道这个有多棒了!
FLAG就是给外面的接口,用来控制是否裁剪。
这篇文章就举例子说明的这个用法。
#ifndef LOVE_FISHC
#define LOVE_FISHC
class Rational{ … };
#endif
ifndef先判断后面的字符是否定义过,如果没定义,就在下面定义一下。如果已经定义了,就不执行里面的代码。
这样就利用这个字符来探测是否重定义了。
这个字符的命名规则:将原头文件名字母都变大写,实心点用下划线代替。例:【Halcon.h -> HALCON_H】
命名空间(作用域):
最大的区域是全局作用域,最小的区域是一个代码块。例如:
{
int a = 20;
}
//a在此处已经不存在了
如果没有命名空间,且工程很庞大,因为没有两样东西可以有同样的名字,只能通过详细的命名描述加以区分。
这个时候就正好使用命名空间。使变量只在命名空间内是独一无二的就ok.创建格式如下:
namespace myNamespace
{
// 全部东西
}
注意,结尾不加分号,这不是结构不是类。例如,通过这样,可以把两个person区分开,只要加上各自的命名空间就可以在同一个作用域使用啦~
namespace author
{
std::string person;
}
namespace programmer
{
std::string person;
}
具体用法:
把.h文件中代码用namespace括起来(注意,不要括进去预处理代码),把.cpp文件中代码也用namespace括起来(同前面一样,不要括进去预处理代码)。
最后在调用这个.h的cpp里,在前面声明一下using namespace xxx【其实是不推荐这么用的,要是这么用,就失去了使用命名空间的意义了】
正确的用法是,在调用这个.h的cpp里,使用这样的格式:【(命名空间的名)::(变量或函数)】
其实这个命名空间的使用,有三种:(例)
1. std::cout << "xxx" << std::endl; //哪里使用,就在哪里添加命名空间的标识
2. using namespace std; //直接在include下一行写,不推荐这么用,失去命名空间的意义了
3. using std::cout; //直接在include下一行写,
cout << "xxx" << std::endl; (要使用哪个变量或函数,就提取出来哪个)
cout提取了,但endl没提取,所以cout不需要std前缀,而endl仍需要。
关于链接:
查资料的时候,有这么几个文章讲得很好,还很仔细,但临时时间不够,留着以后再看。
《理解C++的链接:C++内链接与外链接的意义》、《c c++ static之谈》、《c语言和堆栈》、
12月3号再整理成文字。
---------------------------------------------------------------------------------------------------
提到链接性,就要把存储持续性和作用域也拎出来。
下面这一张图,就说清了这三个概念之间的关系。
自动:存在于代码块中,就是局部变量。比如在一个函数体里声明的变量,函数运行结束后就自动释放了,内存自动归还给系统。
寄存器:还没到控制这种变量的水平和场合,没研究。~~~哈哈哈
静态,无链接性:这种就还是局部变量。也是比如在函数体里声明的static前缀的变量,外面不能用,也就没有外部链接性。然后变量本身就在代码块内部,也不涉及到内部链接性。so,无链接性。静态无链接性的变量,只在该代码块中可用,但好处是,这种变量在该代码块不处于活动状态时仍存在。【这个类型是加了static的】
静态,外部链接性:声明的地方就不在代码块里了,而是在文件中。例如在.cpp或者是.h中,声明一下变量,也不加static,这样就拥有外部链接性了。其实这个变量在文件内部里都能用,就属于是全局变量了。而所谓的外部,就是在其他文件中使用,比如在哪个文件中使用,就在那个文件中用extern再声明一下这个变量就ok啦。(测试过,用extern声明的话,不用包含对应头文件,直接extern声明一下,就能用。)【这个类型是不加static的】
静态,内部链接性:声明的地方还是不再代码块里,应该在文件中,和上面那种外部链接性的是在一个位置声明的。只是,这个前面加一个static前缀,这样就有内部链接性了。外面文件不能使用这个变量了,就是extern也不行了。静态内部链接性extern不行的时候,使用include包含.h就ok了,这样就可以使用别的文件中的静态内链接变量了。static前缀就是为了使这种位置的变量具有内部链接性。【这个类型是加了static的】
差点儿忘说一个事儿,当外部变量和局部变量冲突的时候(也就是同名,同类型),外部变量会暂时被局部变量覆盖(就跟函数被重载了似的)。等局部代码块执行结束后,又恢复到了外部变量。此刻局部的那个变量已经被释放了,此刻只剩下这个外部变量还在内存中了。
还有const的事儿,如果声明的静态外部链接性的变量前面有const,那会秒变内部链接性,因为const自带static属性。但如果非要外部用,可以在初始化声明的时候,最前面加个extern。注意!!!是初始化声明的时候,就加extern。然后在要用这个变量的其他文件中,就正常加上extern声明就行了,不用初始化,因为一定初始化过了。