原生bool
c++支持原生bool
在C语言中,如果要使用bool,需要包含stdbool.h,而在stdbool.h中是用宏的方式定义了一个0和1,true=1,false=0。
但是这种定义不是真正原始意义上的bool,只是用了代替品来代表bool。在C++中的true和bool才是真正意义上的bool。C++中bool,0为false,非0为true。其它各种方式的bool,(如BOOL),都不是原生bool,其中的区别是非常大的:
>
真/假 | 原生bool | define定义的bool |
---|---|---|
true | 非0 | 1 |
false | 0 | 0 |
其中,false的值都是0,没问题。但是,在true中,原生bool对于非0的值都认为是true,而define的true,定义为1。举个例子:
-1对于原生bool来说,它就是true。而define的true并不会认为它是true。但是,我们平时用的时候完全没毛病啊,并不会出现-1不能判断为true的情况。这是因为,编译器为此做了很多工作,将它进行了转换。
注意:_Bool是在c98之后加上的布尔类型,等同于bool。在使用布尔类型的时候,建议使用bool,会更加安全
头文件的三种标准
标准1:C++特有的标准库
如:include< iostream >;
没有.h后缀,后缀名用于进行区分使用
标准2:前缀cxxx,从C继承来,但是符合C++标准的库
如:#include< cstdio >
标准3:从C继承来的库(不符合C++标准)
如:#include< stdio.h >
补充:stdafx与stdafx.cpp是VC特有的东西,也可以没有。称为预编译头,微软认为给我们了便利,但其实没有,也是不被C++承认的。有它没它都可以
域作用符
符号
::
作用
访问指定的命名空间
示例1:
int num=10;
std::cout<< num;
std::cout<< “试试”;std代表的是一个命名空间叫做std,是一个非常特殊的命名空间,这个命名空间中的所有函数及变量都是标准库中的函数及变量(可通过打开文档查看)
示例2:
int num=100;
int main()
{
int num=10;
std::cout<<num;
}代码解析:
由此打印出的值为10,也就是局部变量的值。根据就近原则,局部变量将全局变量num覆盖了如果需要在此处打印全局变量的值,那么应该怎么做的?
int num=100;
int main()
{
int num=10;
std::cout<<::num;
}在num之前加了域作用符(::),因为域作用符之前没有说明命名空间,所以默认为全局。也就是通过这个域作用符,规定了此处所用的num属于全局的那个num。
C++中加了命名空间,可以用来控制作用域,可以在变量名之前加::用来说明是在哪个命名空间中
示例3:
namespace Podeu
{
int num=20;
}
int num=100;
int main()
{
int num=10;
std::cout<<::num;
}
std::cout<<num+::num+Poedu::num;此时打印的结果就是局部变量num+全局变量num+Poedu中的num的和,也就是130。
补充:在写C项目的时候,碰到了各种各样的ndex和count,这些变量都可以通过命名空间来避免冲突。
new和delete
作用
C++为我们提供的进行堆操作的运算符
注:在C语言中,想在堆上面进行一些操作的时候,使用的是两个函数:malloc和free。
示例
int main()
{
int *pNum=new int(100);
//分配了一个int类型大小的空间,并将值设为100.
std::cout<<*pNum;
delete pNum;
//分配连续的内存空间
int *pArr=new int[10];
delete[] pArr;
return 0;
}与malloc和free的区别
ew和delete是运算符,它们不是函数,malloc和free是一个函数。
但是,注意,这两对都是配套使用的
重载
C++当中一个非常强大的机制
示例:std::cout<<1;
std::cout<<‘c’;
std::cout<<”Try”;
std::cout<<1.002;上例中,我们使用了一个函数cout输出了int型的1,char型的c,char*型的Try,float型的1.002。这在C语言中是很难得的,如果我们要达到这样的效果,也可以,但是我们需要做非常多的事情。而C++中的重载却让这件事情变得非常简单了,构成重载后,它会根据参数找到适合的函数进行工作。
原理
我们在上例中使用了同一个函数:cout,这个函数名在我们看来是一样的,但其实是不一样的,编译器会根据后面的参数类型进行匹配。
从反汇编中看,每个Mycout所Call的地址都是不一样的,也就是说,我们把它们都成为cout,但是它其实是几个不同的函数,每一个函数都有自己的空间
那么为什么能够做一一匹配呢?因为编译器会保存一个符号表的东西(记录:变量占用的空间(长度),解析方式(和类型相关)
编译器同时记录函数的参数类型,传入的参数类型,再进行匹配,其记录符号可以是这样的:
MyCout@int
MyCout@char
MyCout@char*
MyCout@float
MyCout@int@char
MyCout@char@int它将每一个函数都进行了命名粉碎(命名重定向),它在符号表中的存储名字是函数名加上参数类型,使得每一个函数名变得不同。
在本地中用没有问题,但是被其他人调用的时候,实际上个名称已经被更改了。可以用extern C,C编译模式下进行编译时不会有命名粉碎的。
重载规则:
函数名相同,参数不同即可构成重载,与类型(返回值)无关。类型不同,函数名、参数相同构不成重载
如:
int MyCout(int i,char c);
void MyCout(int i,char c);这样是不能构成重载的,尽管返回值不同,但是两者的函数名和参数完全相同,这样改改就可以了:
int MyCout(char c,int i);
void MyCout(int i,char c);这样改一下,它实际的名字就变成了MyCout@char@int 与 MyCout@int@char,这两者是不同的,不会发生冲突
注意:实际的命名粉碎不是这样的,还会加上一些类和命名空间等等的一些东西。