这里写目录标题

  • 1.头文件
  • 2.#ifdefine 和#pragma once的区别
  • 3.说明符和限定符
    • (1) cv-限定符
    • (2)mutable
    • (3)const
  • 4.函数链接性
  • 5.语言链接性
  • 6.new的简单使用
  • 7.名称空间

1.头文件

头文件包含结构声明和使用这些结构的函数的原型(声明函数)

实际上,我们如果要自己写一个头文件,那么头文件里面最好不要有函数的定义,和变量的声明,否则会产生错误。而正确的做法是,在头文件里面包含函数的声明,而函数的定义放在另一个cpp文件里面。那么就简单的知道了,一个头文件和一个实现头文件的.cpp文件是配套使用的。头文件不定义函数,只声明函数

那么如何创建头文件呢?

  1. 新建一个项目,后缀名为.h
  2. 在第一行写上 #pragma once
  3. 开始写函数声明,结构声明这些

很简单,下面是我自己写的。

首先建立一个头文件

然后建立一个一样名字的cpp文件来定义头文件声明的函数

最后用一个源程序测试

测试结果

上面可以说是很简单易懂,先简单了解一下,下面会因此展开一些问题。

2.#ifdefine 和#pragma once的区别

为了避免同一个文件被include多次,C/C++中有两种方式,一种是#ifndef方式,一种是#pragma once方式。在能够支持这两种方式的编译器上,二者并没有太大的区别,但是两者仍然还是有一些细微的区别。

上面已经提到,建立头文件的时候,在文件第一行要写上 #pragma once 这条语句,那么实际上,还可以这样写

#ifndef MYSELF_H_
#define MYSELF_H_....#endif

那么看到这些确实很疑惑。下面来解读一下这些语句

第一句话#ifndef MYSELF_H_的意思是如果这个标识符被定义了,那么就不再定义,直接跳到#endif后面一句。如果没有定义,那么走到下一行,定义该标识符,然后,编译器将查看#ifndef和#endif之间的内容.

这种方法不能防止编译器将文件包含两次,而只是让它忽略除第一次包含之外的全部内容。

至于区别是什么,暂时还不知道,先挂在这里

3.说明符和限定符

有些被称为存储说明符或cv-限定符的C++关键字提供了其它有关存储的信息,下面是存储说明符;

  • auto
    编程时常常需要把表达式的值赋给变量,这就要求声明变量时清楚的知道表达式的类型。然而有些情况是声明的变量的类型我们并不知道,比如在模板编程时。为了解决这个问题,C++11引入了auto类型说明符,用它来让编译器替我们去分析表达式所属的类型。
  • register
  • static
  • extern
  • thread_local
  • mutable

(1) cv-限定符

  • const
  • volatile

上面两个关键字就是cv限定符。
首先,我们对const很熟悉,无论是对常规变量的初始化,还是对常量指针,指针常量这些乱七八糟的对象,都会用到const. 那么,volatile是什么呢?

volatile的本意是“易变的”,volatile关键字是一种类型修饰符,用它声明的类型变量表示可以被某些编译器未知的因素更改,比如操作系统、硬件或者其它线程等。遇到这个关键字声明的变量,编译器对访问该变量的代码就不再进行优化,从而可以提供对特殊地址的稳定访问。

(2)mutable

mutable指出,即使结构(或类)变量为const,其某个成员也可以被修改。例如:

struct data
{char name[30];mutable int accesses;
};const date veep={"lby",12};
strcpy(veep.name,"ybl");    //不允许,因为const限定符
veep.accesses++; //允许,因为mutable解除const的限制

(3)const

(1)在C++中,const限定符对默认存储类型稍微有些影响。在默认情况下全局变量的链接性是外部的,但是const的全局变量的链接性是内部的。也就是说,在C++看来,全局const定义就像使用了static一样。

(2)将一组常量放在头文件中,由于const常量是的链接性是内部的,所以每个文件相当于有一组自己私有的常量,互不相干。

(3)在函数和代码块中声明const时,其作用域为代码块,即仅当程序执行该代码块中的代码时,该常量才是可用的。这意味着在函数或代码块中创建常量时,不必担心其名称与其它地方定义的常量发生冲突。

(4)如果需要使用该常量的链接性为外部的,则可以使用extern关键字来覆盖默认的内部链接性: extern const int state=50;

4.函数链接性

(1)函数也有链接性,在默认情况下,函数的链接性是外部的,也就是说,一个文件里面的函数可以在其它文件里面共享。

(2)函数的存储持续性都是自动为静态的,即整个程序运行期间一直存在。

(3)可以使用static关键字将函数的链接性设置为内部,使之只能在一个文件中使用。但是必须同时在原型和函数定义中使用该关键字。

static int private(double x);  //函数声明
...
static int private(double x)   //函数定义
{....
}

这样的话,该函数就只在该文件可用,其它文件不共享。其它文件当然可以再次使用同名定义函数。和变量一样,在定义静态函数的文件中,静态函数将覆盖外部定义,因此即使在外部定义了同名的函数,该文件仍将使用静态函数.

(4)内联函数不受单定义规则制约。这允许程序员能够将内联函数的定义放在头文件中。这样,包含了头文件的每个文件都有内联函数的定义。然而,C++要求同一个函数的所有内联定义都相同。

(5)每个外部函数只能有一个定义,如果有两个,则会报错。

(6)C++在哪里查找函数
如果文件中的函数原型指出该函数时静态的,则编译器将只在该文件中查找函数定义。否则将在所有的程序文件中查找。如果在所有的程序文件中没有找到,编译器将在库中查找。这意味着如果定义了一个与库函数同名的函数,编译器将使用程序员定义的版本,而不是库函数。

5.语言链接性

在c语言中,一个名称对应一个函数,为满足内部需要,c语言编译器可能将spiff这样的函数名翻译为_spiif。这种方式被称为C语言链接性。但在C++中,同一个名称可能对应多个函数(函数重载等),那么对于编译器来说,就必须将这些相同函数名翻译成不同的符号名称,所以C++编译器将执行名称矫正或名称修饰。这叫做C++语言链接。。例如,可能将spiff(int)转换为_spiff_i,将spiff(double,double)转换为_spiff_d_d.

那么提到了C和C++对于语言链接有着不同的处理方案,即“翻译名称”不一样,那么当在C++程序中使用C库中预编译的函数,将会出现什么情况呢?例如如下代码:

spiff(22);

在C库中,它的符号名称为_spiff,但对于我们假设的链接程序来,C++查询约定时查找符号名称_spiff_i。这怎么办呢?
答案是:指出约定。

extern "C" void spiff(int);  //显式使用C
extern void spoff(int);  //默认使用C++,因为是在C++程序中,所以默认的是C++
extern "C++" void spaff(int);  //显式使用C++

6.new的简单使用

(1)new的初始化

int *pi=new int(8); //意思是创建一个int类型的变量,它的值为8,pi指向这个值,pi是这个值的地址

如果需要初始化结构体,那么就需要用大括号,但是这要求编译器支持C++11.

struct where{double x;double y;double z;};
where * one=new where{3.3,123.3, 9.9 };
int *a=new int [4] {1, 2, 3, 4};

(2)new分配内存失败
早10年,C++让new返回空指针,单现在将引发异常std ;bad_alloc。

(3)定位new运算符

通俗来说,定位new运算符就是在指定位置开辟一个空间,然后使用这个空间,这就是“定位”。不过,这个指定的空间不是重新去堆新开辟,而是在已有数组中借走一部分。

#include<iostream>
#include<new>
using namespace std;struct chaff
{char dross[20];int slag;
};char buffer1[50];
char buffer2[100];int main()
{chaff* p1, * p2;int* p3, * p4;p1 = new chaff;p3 = new int[20];p2 = new(buffer1) chaff;   //从buffer1数组中借走一个chaff的长度,观察到是从buffer1[0]开始借走的p4 = new(buffer2)int[20];   //从buffer2数组借走80个字节
//下面的赋值是观察借走的是哪一部分*p2 = {"boy",3};for (int i = 0; i < 20; i++)*(p4 + i) = i + 1;cin.get();return 0;}

那么上面的程序可以知道,重定位new运算符不是在堆里面开辟空间,而是重复利用已经有的数组空间。再一个,如果不设置偏移量,那么每次这样:new(buffur1)chaff,都是在buffer1数组头借用空间,new不会去检查这个空间是否被用过,那么如果想要借走buffer1数组其它位置的空间,就需要设置偏移量,比如new(buffer1+5*sizeof(int))chaff,那么借走的空间将是buffer[4]-buffer[28]。

定位new运算符的工作原理:返回传递给它的地址,并将其强制转换为void *,以便能够赋给任何指针类型。

7.名称空间

在C++中,随着项目的增大,可能会产生这样一个问题:可能会有“变量名”(这里的变量名指所有需要手动输入的名称)重复,导致名称冲突。

C++标准提供了名称空间工具,以便更好地控制名称的作用域。

传统的C++名称空间
首先知道两个术语:

  • 声明区域
  • 潜在作用域

声明区域是指一个变量或函数可以在其中声明的区域。潜在作用域是指声明点到声明区域结束的范围内。但变量的可见性会因为其潜在作用域中是否存着同名覆盖的局部变量而影响。

新的C++名称空间
通过定义一种新的声明区域来创建命名的名称区域,这样做的目的之一是提供一个声明名称的区域。一个名称空间中的名称不会与另一个名称空间的相同名称发生冲突,同时允许程序的其他部分使用该名称空间中的东西。

下面介绍一个术语:作用域解析运算符::
作用域解析运算符的作用是用来访问名称空间中的名称的。

首先,先创建名称空间Boy,Girl。

namespace Boy
{char name[100];int sex;int age;void act();  //这里先写原型,可以在别的文件再去定义
}namespace Girl
{char name[100];int sex;int age;
}

如果要使用变量sex,name,age,则可以使用作用域解析运算符来区分。

Boy::age=10;
Girl::age=11;
Boy::act();  //可以有函数哦,但是注意,函数的定义一定要写在名称空间里面。

总结:绕来绕去,简而言之,就是在内存分配空间分别存放各自需要的变量,这些变量可以一样,可以不一样,但是前提是加上::用来区分。

using 声using 编译指令

C++提供两种机制来使用便捷名称空间。

(1)using 声明
using声明由被限定的名称和它前面的关键字using组成:
例如:using Boy::age;

using声明将特定的名称添加到它所属的声明区域。
例如在main里面:

int main()
{using Boy::age;  //将Boy里面的age的作用域放置到main函数里面,而且将会覆盖全局变量。age=10;  //等价Boy::age=10;
}

(2)using编译指令
using声明使一个名称可用,而using编译指令使所有的名称都可用。using编译指令由名称空间名和它前面的关键字using namespace 组成,它使名称空间中的所有名称都可用,而不需要作用域解析运算符::

#include<iostream>
using namespace std;  //这里的作用域使全局
int main()
{using namespace Boy;  //这里的作用域是main函数
}

C++primeplus p247-277相关推荐

  1. 一起教育科技递交招股书:收入增速超277.48%,或成纳斯达克最大教育概念股

    北京时间11月14日,国内领先的中小学生在线作业平台--一起作业及其母公司一起教育科技正式向美国证监会(SEC)递交了招股说明书,拟在纳斯达克上市,承销商为摩根士丹利.高盛和美银证券. 根据招股书内的 ...

  2. UOJ #277 BZOJ 4739 定向越野 (计算几何、最短路)

    UOJ #277 BZOJ 4739 定向越野 (计算几何.最短路) 手动博客搬家: 本文发表于20181208 14:39:01, 原地址https://blog.csdn.net/suncongb ...

  3. UOJ #277 BZOJ 4739 [清华集训2016]定向越野 (计算几何、最短路)

    手动博客搬家: 本文发表于20181208 14:39:01, 原地址https://blog.csdn.net/suncongbo/article/details/84891710 哇它居然显示出图 ...

  4. 贪心+构造 Codeforces Round #277 (Div. 2) C. Palindrome Transformation

    题目传送门 1 /* 2 贪心+构造:因为是对称的,可以全都左一半考虑,过程很简单,但是能想到就很难了 3 */ 4 /**************************************** ...

  5. Acwing 277. 饼干

    Acwing 277. 饼干 题意: 圣诞老人共有 M 个饼干,准备全部分给 N 个孩子. 每个孩子有一个贪婪度,第 i 个孩子的贪婪度为 g[i]. 如果有 a[i] 个孩子拿到的饼干数比第 i 个 ...

  6. jep使用_JEP 277“增强弃用”非常好。 但这是一个更好的选择

    jep使用 维护API很难. 我们正在维护非常复杂的jOOQ API. 但是就语义版本而言,我们遵循相对宽松的规则 . 当您阅读Brian Goetz和其他人关于在JDK中保持向后兼容性的评论时,我只 ...

  7. JEP 277“增强弃用”非常好。 但这是一个更好的选择

    维护API很难. 我们正在维护非常复杂的jOOQ API. 但是就语义版本而言,我们遵循相对宽松的规则 . 当您阅读Brian Goetz和其他人关于在JDK中保持向后兼容性的评论时,我只能对他们的工 ...

  8. Codeforces Round #277 (Div. 2) 题解

    Codeforces Round #277 (Div. 2) A. Calculating Function time limit per test 1 second memory limit per ...

  9. 2018年排名Top 100的Java类库——在分析了277,975份源码之后得出的结论

    最近,OveOps公布了The Top 100 Java Libraries in 2018 - Based on 277,975 Source Files,Hollis查看了这份榜单,做了翻译和补充 ...

  10. GCC 编译报错:程序中有游离的 \357’ \273’ \277’ 等

    中文下报错内容是: cc -c -I. test.c -o output/obj/test.o test.c:1: 错误:程序中有游离的 \357' test.c:1: 错误:程序中有游离的 \273 ...

最新文章

  1. 不同的设计模式的特点总结
  2. 程序员职业规划的3个锦囊
  3. Http中Get/Post请求区别
  4. [转]让Linux的tty界面支持中文
  5. Android开发常用命令
  6. ffmpeg 无法找到libpostproc的问题
  7. BestCoder15 1002.Instruction(hdu 5083) 解题报告
  8. Php AES加密、解密与Java互操作的问题
  9. sqlyog-mysql_SQLyog
  10. 手游的巨头时代,中小厂商该何去何从?
  11. zen3 服务器芯片,7nm+工艺Zen3两线出击:EPYC服务器先发 锐龙5000紧跟
  12. 便宜又大碗!AI将画廊轻松搬到自家墙壁;用隐写术在图像中存储文件;免费书·算法高维鲁棒统计;关节式手部模型数据集;前沿论文 | ShowMeAI资讯日报
  13. 好扑科技技术副总裁戎朋:从海豚浏览器服务器端研发主管到区块链,揭秘区块链技术之路...
  14. 计算机专业网名英语翻译,英语网名大全带翻译【三篇】
  15. java 地铁费_Java练习题_Map集合,遍历车站编号及名称、计算地铁票价。
  16. 点触科技安全验证新模式与逐浪CMS3.9.3新功能预览
  17. 云计算基础架构 (三)Mongodb
  18. 机器学习之逐次下降法(机器学习算法原理与实践)郑捷 (P159-p163)
  19. (贪心)CF1428E. Carrots for Rabbits
  20. plsql查看oracle归档日志,Oracle 日志分析工具LogMiner的安装使用

热门文章

  1. 【iOS】音频播放之AVAudioPlayer,AVPlayer,AVQueuePlayer
  2. 防火墙配置【最详细的实验演示】
  3. 核废料该如何处理,奥特曼发话了…
  4. oracle 获取当前时间并减去一年
  5. 芳华永在!一个老运维的20年奋斗史
  6. VS2019无法登陆解决办法
  7. Vue $axios 插件使用
  8. vscode写python爬虫_用 VS Code 写 Python,这8个扩展装上后无敌了!
  9. jq循环赋值input
  10. 深搜算法实例:老鼠走迷宫(一)