目录
还记得第一次写C语言的hello word吗
- //text.c
- #include
-
- int main()
- {
- printf("hello word!\n");
- return 0;
- }
'运行
这是C++版的
- //text.cpp
- #include
- using namespace std;
- int main()
- {
- cout << "hello word! \n" << endl;
- return 0;
- }
C++ 诞生于c之后,c++兼容了c,我们重点了解c++中不同于c的部分
定义命名空间,需要用到namespace关键字,后面跟命名空间的名字,然后接一对{}即可,{}中即为命名空间的成员。命名空间可以定义变量/函数/类型等。
namespace bit
{
//定义变量
int rand=10;//定义函数
int Add ( int a , int b )
{
return a +b ;
}//定义类型
struct Node
{
struct Node* next;
int val;
};}
调用域下面的变量/函数等
bit ::rand
- namespace text1 {
- int rand = 0;
- }
- namespace text2 {
- int rand = 10;
- }
C++中域有函数局部域,全局域,类域;域影响的是编译时语法查找一个变量/函数/类型出处(声明或定义)的逻辑,所以有了域隔离,名字冲突就解决了。局部域和全局域除了会影响编译查找逻辑,还会影响变量的声明周期,命名空间域和类域不影响变量声明周期。
- //text.cpp
- #include
- using namespace std;
-
- namespace bit
- {
- int rand;
- int a = 2;
- int Fun(float c, float d)
- {
- return c * d;
- }
- }
- int Fun(int c ,int d )
- {
- return c + d;
- }
- int a = 1;
- int main()
- {
- int a = 0;
-
- printf("%d\n", a);
- // a没有被域限定 代码从上往下走,main 函数下被重新赋值 a=0,所以输出0
- printf("%d\n", ::a);
- //a被::域限定符限定,但左边没有元素,默认为全局域,a=1所以输出1
- printf("%d\n", bit::a);
- //a被::域限定符限定,左边有域名,限定在自定义的域,在bit域中a=2,所以输出2
- printf("%d\n",Fun(1,2));
- // a没有被域限定 代码从上往下走,找到自定义函数Fun调用Fun实现相加,输出3
- printf("%d\n", ::Fun(1, 2));
- //a虽然有域限定符,但是并没有限定范围,还是全局域找到Fun实现相加,输出3
- printf("%d\n", bit::Fun(1,2));
- //a被::域限定符限定,左边有域名,限定在自定义的域,在bit域中找到Fun实现相乘,输出2
-
- }
验证答案

namespace只能定义在全局,当然他还可以嵌套定义
- //text.cpp
- #include
- using namespace std;
-
- namespace bit
- {
- int rand;
- namespace aa
- {
- int rand=1;
- }
- namespace bb
- {
- int rand=0;
- }
- }
-
- int a = 1;
- int main()
- {
-
- printf("%d\n", bit::aa::rand);
- printf("%d\n", bit::bb::rand);
- return 0;
- }

项目工程中多个文件中定义的同名namespace会认为是一个namespace,不会冲突
C++标准库都放在一个叫std(stdndard)的命名空间中
- using namespace std;
- //展开std头文件
- using namespace bit::rand;
- //展开bit中的rand
一般日常练习中我们可以using namespace std,世纪项目开发中不建议using namespace
- //text.cpp
- #include
- using namespace std;
-
- int main()
- {
- int i = 123;
- int j = 234;
- int x;
- int y;
- cin >> x >> y;
- //控制台手动输入x,y
- cout << i << j << endl;
- //输出i和j并且最后换行
- return 0;
- }
但是一对<< <<内只能有一个变量,否则编译器报错

![]()
在c++中我们没有包含
- //text.cpp
- #include
- using namespace std;
- //全缺省
- void Fun1(int a=10,int b=20,int c=30)
- {
- cout << "全缺省" << endl;
- cout << "a=" << a << endl;
- cout << "b=" << b << endl;
- cout << "c=" << c << endl;
-
- }
- //半缺省
- void Fun2( int a ,int b=10 ,int c=20)
- {
- cout << "半缺省" << endl;
- cout << "a=" << a << endl;
- cout << "b=" << b << endl;
- cout << "c=" << c << endl;
- }
-
- void Fun3(int a, int b, int c)
- {
- cout << "普通" << endl;
- cout << "a=" << a << endl;
- cout << "b=" << b << endl;
- cout << "c=" << c << endl;
- }
- int main()
- {
- Fun1();//没有传参时,使用参数的默认值
- Fun2(10);//传参时,使用的指定值
- Fun3(10,20,30);//传入指定值
-
-
-
- return 0;
- }

C++支持在同一作用域中出现同名函数,但是要求这些同名函数的形参不同,可以是参数个数不同或则类型不同。这样C++函数调用就表现出了多态行为,使用更加灵活。C语言是不支持同一作用域中出现同名函数的。
- //text.cpp
- #include
- using namespace std;
- //1.参数类型不同
- int Add(int a, int b)
- {
- cout << "int Add(int a, int b)" << endl;
- return a + b;
- }
- double Add(double a, double b)
- {
- cout << "double Add(double a, double b)" << endl;
- return a + b;
- }
- //2.参数个数不同
- int Add(int a)
- {
- cout << "int Add(int a)" << endl;
- return a;
- }
- double Add(double a, double b)
- {
- cout << "double Add(double a, double b)" << endl;
- return a + b;
- }
- //3.参数类型顺序不同
- void fun(int a, char b)
- {
- cout << "void fun(int a, char b)" << endl;
-
- }
- void fun(char b, int a)
- {
- cout << "void fun(char a, int b)" << endl;
-
- }
- int main()
- {
- cout << "参数类型不同" << endl;
- cout << Add(3,5)<< endl;
- cout << Add(3.1,5.0) << endl;
- cout << "参数个数不同" << endl;
- cout << Add(3) << endl;
- cout << Add(3.1, 5.0) << endl;
- cout << "参数类型顺序不同" << endl;
- fun(3, 'x');
- fun('x', 5);
-
- return 0;
- }
注意:返回值不能作为判断是否重载的依据因为容易产生歧义,如下面的代码f()调用
- //text.cpp
- #include
- using namespace std;
- void f()
- {
- cout<<"f()<
- }
- void f(int a=10)
- {
- cout<<"f(int a=20)"<
- }
- int main()
- {
- f();
- return 0;
- }

引用不是新定义一个变量,而是给已存在变量去了一个别名,编译器不会为引用变量开辟内存空间,它和它引用的变量共用同一块内存空间
类型&引用别名=引用对象;
- //text.cpp
- #include
- using namespace std;
-
-
- int main()
- {
- int a = 0;
- //引用:b和c是a的别名
- cout << "a=" << a <<" " << &a << endl;
- int &b = a;
- cout << "b=" << b <<" " << &b << endl;
- int& c = a;
- cout << "c=" << c << " " << &c << endl;
- //也可以给b取别名,d还是相当于a的别名
- int& d = a;
- cout << "d=" << d<< " " << &d << endl;
-
- return 0;
- }
值一样,地址也一样

只是取得“外号”罢了

传统的交换函数
- void Swap(int* x,int* y)
- {
- int tem=*x;
- *y=*x;
- *x=tem;
- }
现在只要传引用就能解决
- void Swap(int& rx,int&ry)
- {
- int tem=rx;
- rx=ry;
- ry=tem;
-
- }
- //text.cpp
- #include
- using namespace std;
-
-
- int main()
- {
- int a = 0;
-
- int ra&;
- //编译器报错,未给初始化引用
-
-
- //一个变量可以有多个别名
- int &b = a;
- //引用:b和c是a的别名
-
- int& c = a;
- //也可以给b取别名,d还是相当于a的别名
-
- int& d = a;
- //d是a的别名
-
- //给别名取别名
- int& f = b;
-
- return 0;
- }

不需要注意的是类似于int& rb=a*3; double d=12.34 ; int & rd=d;这样一些场景下a*3的值结果保存在一个临时对象中,int& rd=d 也是类似,在类型转换中会产生临时对象存储中间值,也就是说,rb和rd引用的都是临时对象,而C++规定的临时对象具有常性,所以在这里就触发了权限放大,必须要用常引用才可以
所谓临时对象就是编译器需要一个空间暂存表达式的求值结果时临时创建的一个未命名的对象,C++把这个未命名对象叫做临时对象
- //text.cpp
- #include
- using namespace std;
-
-
- int main()
- {
- int a = 0;
- //定义整型a=0
- const int b = 10;
- //定义整型常量b=10
- int& ra = a;
- //给ra引用a,权限一样,没问题
- const int& raa = a;
- //给raa引用a ,权限缩小,也没问题
- int& rb = b;
- //给rb引用b,有const修饰到没有const修饰,权限放大,编译器报错
- const int& rbb = b;
- //给rbb引用b,有const修饰到const修饰,权限一致,没问题
-
-
- int& ab = (a + b);
- //编译器报错,表达式的结果存在临时对象里,临时对象具有常性
-
- const int& ab = (a + b);
- //编译通过
-
- int rd = b;
- int abb = a + b;
- //编译通过,表达式的结果虽然存在临时变量里,这里是将表达式的值拷贝一份给abb没有涉及权限的问题
-
-
- a++;
- ra++;
- //可以执行,没有const修饰
-
- rb++;
- //不存在
-
- rbb++;
- raa++;
- b++;
- //有const修饰,编译器报错
-
- double d = 12.34;
- int i = d;
- //隐式类型转换会产生临时变量,但是值得拷贝不影响
-
- int& ri = d;
- //编译不通过,double转换为int类似,C++规定会产生临时对象,临时对象具有常性,所以这里不加const,权限缩小
- const int& rii = d;
- //编译通过
- return 0;
- }
注意:临时对象只有短暂的生命周期,但是被引用后,生命周期会延长直到引用对象销毁
C++中指针和引用就像两个性格迥异的亲兄弟,指针是哥哥,引用是弟弟,在实践中他们相辅相成,功能具有重叠性,但是各有自己的特点,互相不可替代

从汇编语言来看,引用本质就是指针
- //text.cpp
- #include
- using namespace std;
-
- inline int Add(int x, int y)
- {
- int ret = x + y;
-
- ret += 1;
- ret += 1;
- ret += 1;
- ret += 1;
- ret += 1;
-
- return ret;
- }
- int main()
- {
- int ret = Add(1, 2);
- cout << ret << endl;
-
- return 0;
- }
看一下汇编语言 ,实现内敛了



NULL实际是一个宏,在传统的C头文件(stddef.h)中。C++中NULL可能被定义为字面常量0,或者C中被定义为无类型指针(void*)的常量,不论采取哪种定义。在使用指针时,都不可避免会遇到一些麻烦
C++11中引入nullptr,nullptr是一个特殊的关键字,nullptr是一种特殊类型的字面量,它可以转换成任意其他类型的指针类型。使用nullptr定义空指针可避免类型转换的问题,因为nullptr只能被隐式转换成指针类型,而不能被转换为整数类型