01-c++对c的扩展(上)
一、c++概况
1.c++编程思想
c++的编程思想:面向对象编程、泛型编程。
-
面向对象:将数据和方法封装在一起,形成一个独立的对象,来实现某些特定的功能。C语言是面向过程的编程,是由一个个函数组成的,但函数只封装了功能没封装数据。面向对象则是由一个个对象组成一个完整的项目。
-
泛型编程:主要体现在模板化,一个函数可以处理多种数据类型。
2.面向对象的三大特征
2.1面向过程与面向对象
- 面向过程是C语言的编程思想:先分析项目的实现步骤,然后通过函数实现一个个步骤,最后逐个调用这些函数实现完整的项目;
- 面向对象:即将方法和数据封装为一个对象,通过一个个对象来实现完整的项目。
2.2三大特征
- c++的三大特性:封装、继承、多态
- 封装:将数据和方法封装在一起,并加以权限区分。一般数据私有,方法公有,外界可以通过公有方法操作私有数据;
- 继承:是类和类之间的父子关系,比如 B 类继承于 A 类,那么 B 类就拥有了 A 类的方法和属性,同时 B 类还能扩展自己的方法和属性;
- 多态:一个函数接口,多种方法,可以理解为,调用同一个函数,可以实现不同的功能。
3.第一个c++程序
- 代码演示
#include <iostream> // 头文件包含
using namespace std; // 使用命名空间
int main() {
// std::cout << "Hello World!" << std::endl;
cout << "hello world!" <<endl; // c++的输出函数
int num1, num2;
cin >> num1 >> num2; // 输入函数
cout << "num1 = " << num1 << ", num2 = " << num2 << endl;
return 0;
}
- 运行结果
hello world!
100 200
num1 = 100, num2 = 200
- 说明:
- c++的官方头文件没有 .h ;
- iostream 是标准输入输出流,所有输入输出都来自于这个头文件;
- 第一种打印方法是指明
cout
和endl
来自于std
,如果这样写比较麻烦,就需要用到命名空间using namespace std
先声明,然后就可以简化成第二种写法了; cout
代表输出设备,endl
表示换行,cin
表示输入设备,输入数据时,不同数据用空格隔开;- << 和 >> 代表输出输入的流向,方向不能搞反了。
二、c++对c的扩展
1.作用域运算符
::
两个冒号就是作用域运算符,它描述的是归属问题,如前面代码std::cout
中描述的就是cout
属于std
。
- 代码演示
// 定义全局变量
int num = 10;
void test01()
{
// 定义局部变量
int num = 20;
cout << "局部变量num = " << num <<endl;
cout << "全局变量num = " << ::num <<endl;
}
- 运行结果
局部变量num = 20
全局变量num = 10
- 这里是作用域运算符的一个特殊用法,在正常情况,局部变量和全局变量同名的时候,遵循就近原则,但这里可以通过作用域运算符,让其在局部作用域优先使用全局变量。
2.命名空间
2.1命名空间概述
命名空间:命名空间的本质是为了防止命名冲突,给符号常量、变量、函数、结构体、枚举、类和对象加一个外壳。如两个相同名字的变量 num ,DATA::num 和 NUM::num 是不一样的。
2.2命名空间的定义
- 代码演示
// 定义一个命名空间
namespace AA
{
int num = 100;
void func()
{
cout << "这是命名空间AA里的func函数!" << endl;
}
}
void test02()
{
cout << "num = " << AA::num << endl;
AA::func();
}
- 运行结果
num = 100
这是命名空间AA里的func函数!
- 说明:
- 命名空间只能在全局范围内定义;
- 命名空间里面的成员可以是普通变量,也可以是函数,或其它类型。
2.3命名空间的嵌套
- 代码演示
// 定义一个嵌套命名空间
namespace A
{
int num1 = 10;
namespace B
{
int num2 = 20;
}
}
void test03()
{
cout << "num1 = " << A::num1 << endl;
cout << "num2 = " << A::B::num2 << endl;
}
- 运行结果
num1 = 10
num2 = 20
- 说明:命名空间的嵌套,只要一直访问到最底层就能取出数据。
2.4命名空间的开放性
所谓命名空间的开放性就是已经定义好的命名空间,后面还能给它添加新的成员。
- 代码演示
// 定义命名空间
namespace BB
{
int num1 = 10;
}
// 给命名空间添加变量
namespace BB
{
int num2 = 20;
}
// 给命名空间添加函数
namespace BB
{
void func()
{
cout << "这是命名空间新追加的函数" << endl;
}
}
void test04()
{
cout << "num1 = " << BB::num1 << endl;
cout << "num2 = " << BB::num2 << endl;
BB::func();
}
- 运行结果
num1 = 10
num2 = 20
这是命名空间新追加的函数
2.5命名空间的声明和实现分离
声明和实现分离主要是针对命名空间的成员函数而言的。
- 代码演示
// 定义命名空间
namespace C
{
void func1();
void func2();
}
void C::func1()
{
cout << "func1被执行" << endl;
}
void C::func2()
{
cout << "func2被执行" << endl;
}
void test05()
{
C::func1();
C::func2();
}
- 运行结果
func1被执行
func2被执行
- 说明;
- 声明和实现分离,指函数在命名空间内声明,在命名空间外定义;
- 但函数定义的时候还是得在函数名前面加上作用域限制。
2.6无名命名空间
无名命名空间指在定义命名空间的时候没有名字,意味着命名空间中的标识符只能在本文件内访问,相当于给这个标识符加上了 static,使得其可以作为内部连接。
- 代码演示
// 定义命名空间
namespace
{
int a = 10;
int b = 20;
}
void test06()
{
cout << "a = " << ::a << endl;
cout << "b = " << ::b << endl;
}
- 运行结果
a = 10
b = 20
- 说明:无名命名空间的访问和全局变量的访问一样,在c++里面全局变量是内部连接,与C语言外部连接不同,它只能在当前文件可用。
2.7命名空间取别名
语法:namespace 别名=原名字
。
- 代码演示
namespace longName
{
int a = 11;
int b = 22;
}
void test07()
{
namespace newNAME = longName; // 起别名
cout << "a = " << newNAME::a << endl;
cout << "b = " << newNAME::b << endl;
}
- 运行结果
a = 11
b = 22
2.8using 声明
2.8.1using 声明某个成员
我们使用命名空间::成员
访问绝对麻烦的时候,可用通过using
声明一下。
- 代码演示
namespace D
{
int a = 10;
int b = 20;
int c = 30;
}
using D::b;
using D::c;
// int c = 35;
void test09()
{
cout << "a = " << D::a << endl;
cout << "b = " << b << endl;
int b = 25;
cout << "局部变量b = " << b << endl;
//cout << "c = " << c << endl;
}
- 运行结果
a = 10
b = 20
局部变量b = 25
- 说明:
- 当声明的命名空间成员和局部变量同名时,局部变量优先级高;
- 当声明的命名空间和全局变量同名时,两者没有优先级的概念,命名冲突会报错。
2.8.2using 声明遇到函数重载
- 代码演示
namespace E
{
void func(void)
{
cout << "无参的函数func执行" << endl;
}
void func(int a)
{
cout << "一个参的函数func执行" << endl;
}
void func(int a, int b)
{
cout << "两个参的函数func执行" << endl;
}
}
using E::func;
void test10()
{
func();
func(1);
func(2, 3);
}
- 运行结果
无参的函数func执行
一个参的函数func执行
两个参的函数func执行
- 说明:
- 函数重载:在同一作用域中,函数名相同,函数的参数的个数、类型、顺序不相同都是函数重载。同一函数,传入的参数个数、类型、顺序不同,执行的功能就不相同。和C语言不一样,C语言通过函数名区分不同函数,c++通过函数名和参数共同区分不同函数;
- using 声明的时候,声明的是函数名,因此声明一次,相当于声明了所有同名函数,然后调用的时候就可以根据传入参数不同执行不同功能,这是c++里面的动态多态。
2.8.3声明整个命名空间
我们在前面代码中:using namespace std;
就是声明整个命名空间。
- 代码演示
namespace F
{
int a = 10;
int b = 20;
int c = 30;
}
using namespace F; // 声明整个命名空间
// int c = 40;
void test11()
{
cout << "a = " << a << endl;
cout << "a = " << b << endl;
cout << "a = " << c << endl;
}
- 运行结果
a = 10
a = 20
a = 30
- 说明:
- 声明整个命名空间,即命名空间的所有成员不通过
命名空间::成员
的方法都能访问; - 当要注意全局变量不能和命名空间的成员冲突,否则会报错。
- 声明整个命名空间,即命名空间的所有成员不通过
三、c++常见数据类型增强
1.声明增强
- 代码演示
// 声明全局变量和函数
extern int num1;
extern void func();
void test12()
{
cout << "num1 = " << num1 << endl;
func();
}
int num1 = 100;
void func()
{
cout << "函数func执行" << endl;
}
- 运行结果
num1 = 100
函数func执行
- 说明:
- 在C语言里,同一个文件里,变量和函数的声明可以不加 extern 也能声明;
- 在c++里,即使是同一个文件里,变量和函数的声明必须加 extern。
2.函数参数增强
- 在C语言中,定义函数的时候,函数形参可以不写数据类型也能定义,但是c++的函数形参必须指明形参的数据类型;
- C语言中,定义函数的时候即使没有形参,在调用的时候也可以传参,不会有什么影响,只是传的参数没用罢了;但是c++传参的个数和类型必须和定义的时候保持一致,和前面提到的函数重载可以关联起来,因为即使函数名相同,传入的参数的个数、顺序、类型不同,会执行不同的功能。
3.结构体类型增强
3.1 c++定义结构体变量
C语言中定义结构体变量的时候必须加 struct ,但c++中可以不加。
- 代码演示
// 定义一个结构体
struct stu
{
int num;
char name[32];
};
void test13()
{
// C语言中必须加stuct
// struct stu obj = {101, "jack"};
// c++ 中可以省略
stu obj = {101, "jack"};
cout << "num = " << obj.num << ", name = " << obj.name << endl;
}
- 运行结果
num = 101, name = jack
3.2 c++结构体中定义函数
- 代码演示
struct stu
{
int num;
char name[32];
void func()
{
cout << "我的学号是:" << num << ",我的名字叫:" << name << endl;
}
};
void test13()
{
stu jack = {101, "jack"};
stu rose = {102, "rose"};
jack.func();
rose.func();
}
- 代码演示
我的学号是:101,我的名字叫:jack
我的学号是:102,我的名字叫:rose
- 说明:
- c++ 的结构体中可以直接定义函数;
- 当我们定义两个结构体变量的时候,就开辟了两份空间分别存储两个变量的数据,但是方法是共用的,不管定义多少个结构体变量,方法都只有一份,调用的时候
结构体变量.函数名()
,告诉系统是哪个结构体变量调用函数,就用哪个变量的数据执行函数。
4.bool 类型
bool 类型定义的变量只能赋值: true 真, false 假(赋其他值也不一定报错,但不建议,也无意义)。
- 代码演示
// 定义一个bool类型变量
bool flag = true;
void test14()
{
int i = 1;
while (flag)
{
cout << "i = " << i << endl;
if (i == 5)
flag = false;
i++;
}
}
- 运行结果
i = 1
i = 2
i = 3
i = 4
i = 5
- 说明:bool 类型一般结合循环语句和条件语句来使用。
5.三目运算符增强
- 代码演示
void test15() {
int a = 10;
int b = 20;
// C语言c++都支持的写法
int ret = a > b ? a : b;
cout << "ret = " << ret << endl;
// C语言不支持,c++支持
a > b ? a : b = 100;
cout << "b = " << b << endl;
}
- 运行结果
ret = 20
b = 100
- 说明:
- C语言中,三目运算符返回的是符合条件的变量的值,给值赋值肯定不行,会报错;
- c++中返回的是符合条件的变量的引用,是个变量,因此可以对其返回值赋值。