前言
我们前面已经介绍了C语言和数据结构并且用C语言实现了图以外的其他基本结构,本期开始我们将来系统地学习C++。
本期内容介绍
什么是C++
C++关键字
命名空间
C++输入输出
缺省参数
目录
一、什么是C++?
C 语言是结构化和模块化的语言,适合处理较小规模的程序。对于复杂的问题,规模较大的程序,需要高度的抽象和建模时, C 语言则不合适。为了解决C语言的缺陷和满足市场的需求, 20 世纪 80 年代,计算机界提出了 OOP(object oriented programming:面向对象)思想 ,支持 面向对象 的程序设计语言应运而生。1982 年, Bjarne Stroustrup 博士在 C 语言的基础上引入并扩充了面向对象的概念,发明了一种新的程序语言。为了表达该语言与 C 语言的渊源关系,命名为 C++(C plusplus)。 因此: C++ 是基于 C 语言而产生的(可以理解为他是C语言的升级版,弥补了C语言的缺陷),它 既可以进行C语言的过程化程序设计,又可以进行以抽象数据类型为特点的基于对象的程序设计,还可以进行面向对象的程序设计。
C++历程
1979 年,贝尔实验室的 本贾尼 等人试图分析 unix 内核的时候,试图将内核模块化,于是 在 C语言的基础上进行扩展,增加了类的机制 ,完成了一个可以运行的预处理程序,称之为 C with classes 。
二、C++关键字
我们知道C语言有32个关键字,C++是他的改良版那肯定关键字不会比C语言少,在C++(C++98)中有63个关键字!
三、命名空间
在C/C++的开发中会用到各种库,会定义大量的变量、函数、类等,而一般大型的项目不止一个人在写是一个组或多个组在合作,等各个组完成了相应的功能大家把代码一合并就组成了完整的项目。但这中间就必定会有命名冲突(和库里面冲突、相互冲突)的情况,遇到这种问题该怎么办呢?让另一个改?那这个冲突的有好几万行呢?和你冲突的不止是一个人呢?改就不是解决问题的方法了!C语言实无法解决这个问题的!本贾尼博士为了解决这个问题在C++引入了命名空间!
举个简单的C语言命名冲突的小例子:
#include <stdio.h>
#include <stdlib.h>
int rand = 10;
int main()
{
printf("%d", rand);
return 0;
}
他这里就和库里面的rand函数冲突了
3.1什么是命名空间
命名空间(namespace)是一种将 全局实体(例如函数、类、变量)组织起来以避免命名冲突的机制。可以认为他是一个容器,用于存放相关的代码元素(函数、结构体、全局变量、类等)。 命名空间的作用 是 对标识符的名称进行本地化,以避免命名冲突或名字污染 。
3.2命名空间的定义
用命名空间的关键字 namespace + 名字{} 注意:{}后没有;
namespace cp
{
int rand = 10;
}
这就是一个简单的命名空间!这样定义好全局的实体后,每次等到用的时候指定实体到指定的命名空间去找就OK了,这样即使名字一样也不会造成冲突,因为他们在不同的命名空间里面,作用域不一样,只要命名空间不冲突那就不会出现上面的问题,即使命名空进冲突改起来也比C语言的那种容易!
#include <stdio.h>
#include <stdlib.h>
namespace cp
{
int rand = 10;
}
int main()
{
printf("%d", cp::rand);
return 0;
}
命名空间内可以定义变量、函数、类型等
namespace cp
{
int rand = 10;
int add(int x, int y)
{
return x + y;
}
struct Satck
{
int* a;
int top;
int capxcity;
};
}
命名空间可以嵌套
namespace cp
{
int rand = 10;
int add(int x, int y)
{
return x + y;
}
struct Satck
{
int* a;
int top;
int capxcity;
};
namespace sq
{
int arr[10] = { 0 };
struct Node
{
int* data;
struct Node* next;
};
}
}
一个项目允许多出存在同名的命名空间(例如.h和.cpp里面可以有同名的命名空间)编译器会做后把他们合成一个!
3.3名空间的使用
介绍了什么是命名空间以及命名空间的定义,那命名空间该如何使用呢?假设命名空间是你家的保险柜,你现在需要拿保险柜中的东西,你会怎么做?是不是拿着它的钥匙打开它去取呀!命名空间也是如此需要"钥匙" 作用域限定符(::)来访问!作用域限定符( :: ):作用域限定符用于指明特定标识符所属的作用域。也就是说可以通过使用::找到特定的作用域里面的元素~!
a、命名空间名称+作用域限定符
namespace cp
{
int n = 100;
}
int main()
{
int n = 3;
printf("%d\n", cp::n);
return 0;
}
b、使用using将命名空间中某个成员引入
namespace cp
{
int n = 100;
}
using cp::n;
int main()
{
printf("%d\n",n);
return 0;
}
c、使用using namespace 把命名空间引入
namespace cp
{
int n = 100;
}
using namespace cp;
int main()
{
printf("%d\n",n);
return 0;
}
#include <iostream>
using namespace std;
namespace cp
{
int n = 10;
char c = 98;
namespace sq
{
int num = 100;
int* a;
}
}
int main()
{
printf("%d\n", cp::n);
printf("%d\n", cp::sq::num);
return 0;
}
四、C++的输入输出
在学习所有的语言时都会用该语言写第一个程序:"Hello World",这就势必涉及输入输出,C++的输入输出是咋样的呢?我们来写个Hello World看看!
#include <iostream>
using namespace std;
int main()
{
cout << "Hello World" << endl;
return 0;
}
这里引入官方的命名空间的原因是C++的输出cout 和 输入cin是在官方的库(std)当中的!cout和cin是全局的流对象,endl是特殊的C++符号,表示换行输出,他们都包含在包含<iostream >头文件中。cout(character output) 是C++中的标准输出流对象,用于向标准设备写入数据!cin(character input) 是C++中的标准输入流对象,用于从标准设备中读取数据!<< 是流插入运算符 , >> 是流提取运算符这里大概提一下,由于类和对象和运算符重载没有介绍,后面会详解!
int main()
{
cout << "Hello World" << endl;
int a = 10;
cout << a << endl;
int n = 0;
cin >> n;
cout << n << endl;
char c = 0;
double d = 0.0;
cin >> c >> d;
cout << c << " " << d << endl;
return 0;
}
关于std:平时的学习中可以直接using namespace std;做大型的项目时不要展开!!!用using 将std中的某个成员引入,这样做的好处就避免和std库里面的成员冲突!
五、缺省参数
5.1什么是缺省参数
缺省参数是在函数的声明或定义时给参数一个缺省值,如果调用函数没传参数则用该缺省值,否则用传的参数!
#include <iostream>
using namespace std;
int Add(int x = 1, int y = 1)
{
return x + y;
}
int main()
{
printf("%d\n", Add());
printf("%d\n", Add(10, 20));
return 0;
}
5.2缺省参数的分类
全缺省 :函数的所有参数都给了缺省值!
void fun(int x = 10, int y = 20, int z = 30)
{
cout << x << "-" << y << "-" << z << endl;
}
半缺省 : 函数的部分参数给了缺省值(C++中规定只能从右往左依次给)
void fun(int x , int y = 20, int z = 30)
{
cout << x << "-" << y << "-" << z << endl;
}
注意:
(1)函数的半缺省值必须从右往左依次给,不能隔着给
(2)缺省参数不能在声明和定义时同时出现(这个应该是防止程序员乱搞的)
(3)缺省值必须是常量或全局变量
(4)C语言不支持缺省参数
OK、第二点举个栗子:
int Test(int x = 10, int y = 20);
int Test(int x = 3, int y = 5)
{
cout << x + y << endl;
}
int main()
{
cout << Test() << endl;
return 0;
}
上面的是声明,下面的是定义,他声明和定义给的缺省参数的值不一样,此时调用时编译器就不知道调用哪个了!所以是规定声明和定义时缺省值不能同时出现!
OK,我们改一下,把定义或声明的缺省值去掉: