C++是在C语言的基础上,融入了面向对象编程的思想,并且增加了许多有用的库,从而补充了C语言在语法上的一些不足。简单来说,就是在C语言上不断的添加新的东西,于是就诞生了C++~
1.关键字
首先在关键字上C++(C++98)有63个,而C语言有32个。
2.命名空间
在后续的学习中,变量、函数和类都是存在于全局变量中,由于C语言无法解决命名冲突,于是C++提出了namespace关键字来解决这个问题。
#include <stdio.h>
#include <stdlib.h>
//命名冲突
int rand = 1;
int main()
{
printf("%d\n", rand);
return 0;
}
这段代码运行时就会报错:
这是因为rand本身为一个库函数,而这里当作一个变量使用,造成命名冲突。
那么,命名空间怎么定义呢?
//命名空间定义
namespace wq
{
int rand = 1;
int Add(int x, int y)
{
return x + y;
}
struct Node
{
struct Node* next;
int val;
};
}
其中,wq为命名空间的名字,命名空间中可以定义变量、函数、类型
命名空间也可以嵌套使用:
namespace wq
{
int rand = 1;
int Add(int x, int y)
{
return x + y;
}
namespace qw//嵌套使用
{
struct Node
{
struct Node* next;
int val;
};
}
}
ps:同一个工程中允许存在多个相同的名称的命名空间,但编译器最后会合成同一个命名空间中。
命名空间该如何使用?
namespace wq
{
int a = 1;
int Add(int x, int y)
{
return x + y;
}
}
int main()
{
printf("%d\n", a);//编译报错:error C2065: “a”: 未声明的标识符
return 0;
}
命名空间的使用有三种方式:
方式一:
//加命名空间名称及作用域限定符
printf("%d\n", wq::a);
方式二:
//使用using将命名空间中某个成员引入
using wq::a;
方式三:
//使用using namespace 命名空间名称 引入
using namespace wq;
3.C++输入与输出
#include <iostream>
using namespace std;
//std是C++标准库的命名空间名,C++将标准库的定义实现都放到这个命名空间中
int main()
{
cout << "Hello C++" << endl;
//使用cout标准输出对象(控制台)和cin标准输入对象(键盘)时,
//必须包含<iostream>头文件以及按命名空间使用方法使用std
//endl就像C语言里面的\n,都表示换行输出
//<<是流插入运算符,>>是流提取运算符
printf("Hello C++\n");//C++上也可以使用C语言输出方式
return 0;
}
结果:
C++的输入/输出是自动识别变量类型的
int main()
{
int a = 0;
const char* x = "abcd";
cin >> a;
cout << "x =" << x << endl;
return 0;
}
4.缺省参数
示例:
//缺省参数
void func(int x = 10,double y=1.5,char t ='W')
{
cout <<"x =" << x << endl;
cout <<"y =" << y << endl;
cout <<"t =" << t << endl;
cout << endl;
}
int main()
{
func();//全缺省
func(20);//半缺省
func(20, 2.5);//半缺省
func(20, 2.5, 'Q');
return 0;
}
运行:
注意:半缺省参数必须从左往右依次来给出,不能间隔着给。
如果声明与定义位置同时出现,恰巧两个位置提供的值不同,那编译器就无法确定到底该
用那个缺省值。
5.函数重载
函数重载:是函数的一种特殊情况,C++允许在同一作用域中声明几个功能类似的同名函数,这
些同名函数的形参列表(参数个数 或 类型 或 类型顺序)不同,常用来处理实现功能类似数据类型
不同的问题。
函数重载有三种情况:
//函数重载
//1.函数的类型不同
int add(int x, int y)
{
cout << "int add(int x,int y)" << endl;
return x + y;
}
double add(double x, double y)
{
cout << "double add(double x, double y)" << endl;
return x + y;
}
int main()
{
return 0;
}
//2.函数参数个数不同
void fun(int x)
{
cout << "void fun(int x)" << endl;
}
void fun(int x, int y)
{
cout << "void fun(int x, int y)" << endl;
}
int main()
{
return 0;
}
//3.函数参数类型顺序不同
void fun(int x, char y)
{
cout << "void fun(int x, char y)" << endl;
}
void fun(char x, int y)
{
cout << "void fun(char x, int y)" << endl;
}
int main()
{
return 0;
}
如果函数的返回值不同是否可以重载呢,答案是不可以。因为在调用函数时并不会带上函数的返回值,容易分不清到底调用的是哪个函数,所以在语法上是不支持的。
那么,函数重载的原理——名字修饰,感兴趣的可以自行查看,点这里(非本人制作)。
6.引用
引用不是新定义一个变量,而是给已存在变量取了一个别名,编译器不会为引用变量开辟内存空
间,它和它引用的变量共用同一块内存空间。
注意:引用类型必须和引用实体是同种类型的
引用特性:
//1. 引用在定义时必须初始化
//2. 一个变量可以有多个引用
//3. 引用一旦引用一个实体,再不能引用其他实体
void TestRef()
{
int a = 10;
// int& ra; // 该条语句编译时会出错
int& ra = a;
int& rra = a;
printf("%p %p %p\n", &a, &ra, &rra);
}
常引用:
void TestConstRef()
{
const int a = 10;
//int& ra = a; // 该语句编译时会出错,a为常量
const int& ra = a;
// int& b = 10; // 该语句编译时会出错,b为常量
const int& b = 10;
double d = 12.34;
//int& rd = d; // 该语句编译时会出错,类型不同
const int& rd = d;
}
指针和引用,赋值/初始化 权限可以缩小,但是不能放大
int main()
{
int a = 1;
int& b = a;
// 指针和引用,赋值/初始化 权限可以缩小,但是不能放大
// 权限放大
const int c = 2;
int& d = c;//err
const int* p1 = NULL;
int* p2 = p1;//err
// 权限保持
const int c = 2;
const int& d = c;
const int* p1 = NULL;
const int* p2 = p1;
// 权限缩小
int x = 1;
const int& y = x;
int* p3 = NULL;
const int* p4 = p3;
return 0;
}
使用场景:
做参数
void swap(int& r,int& rt)
{
int tmp = r;
r = rt;
rt = tmp;
}
int main()
{
int a = 1;
int b = 2;
swap(a, b);
cout << "a = " << a << endl;
cout << "b = " << b << endl;
return 0;
}
做返回值
int& Func()
{
static int red = 0;
red++;
return red;
}
int main()
{
int rt = Func();
return 0;
}
引用和指针的区别:
在语法概念上引用就是一个别名,没有独立空间,和其引用实体共用同一块空间。在底层实现上实际是有空间的,因为引用是按照指针方式来实现的。
引用和指针的不同点:
1. 引用概念上定义一个变量的别名,指针存储一个变量地址。
2. 引用在定义时必须初始化,指针没有要求
3. 引用在初始化时引用一个实体后,就不能再引用其他实体,而指针可以在任何时候指向任何
一个同类型实体
4. 没有NULL引用,但有NULL指针
5. 在sizeof中含义不同:引用结果为引用类型的大小,但指针始终是地址空间所占字节个数(32
位平台下占4个字节)
6. 引用自加即引用的实体增加1,指针自加即指针向后偏移一个类型的大小
7. 有多级指针,但是没有多级引用
8. 访问实体方式不同,指针需要显式解引用,引用编译器自己处理
9. 引用比指针使用起来相对更安全
后续会持续更新~