该篇博客主要讲述关于C++发展前言,以及C++祖师爷对C进行改造提升后的新语法进行解释说明,具体内容为:发展历程、命名空间、输入\输出、缺省参数、函数的重载
目录
文章目录
前言
1.什么是C++
2.C++的发展史
3.关于C++的学习
一、关于命名空间
1.含义
2.定义
4.使用
二、C++输入&输出
三、缺省参数
1.缺省参数概念
五、函数重载
1.函数重载概念
前言
1.什么是C++
在之前我们系统学习了C语言,对于C语言来说,它是一种面向过程结果化的语言,适合处理较小规模的程序。当我们面对复杂问题时,需要一种模块化、抽象化形式进行解决,为此,C++就由此而生,它是一种面向多像思想的编程语言。
2.C++的发展史
对于C++的发展而言,我们可以看如下:
阶段 | 内容 |
C with classes | 类及派生类、公有和私有成员、类的构造和析构、友元、内联函数、赋值运算符 重载等 |
C++1.0 | 添加虚函数概念,函数和运算符重载,引用、常量等 |
C++2.0 | 更加完善支持面向对象,新增保护成员、多重继承、对象的初始化、抽象类、静 态成员以及const成员函数 |
C++3.0 | 进一步完善,引入模板,解决多重继承产生的二义性问题和相应构造和析构的处 理 |
C++98 | C++标准第一个版本,绝大多数编译器都支持,得到了国际标准化组织(ISO)和美 国标准化协会认可,以模板方式重写C++标准库,引入了STL(标准模板库) |
C++03 | C++标准第二个版本,语言特性无大改变,主要:修订错误、减少多异性 |
C++05 | C++标准委员会发布了一份计数报告(Technical Report,TR1),正式更名 C++0x,即:计划在本世纪第一个10年的某个时间发布 |
C++11 | 增加了许多特性,使得C++更像一种新语言,比如:正则表达式、基于范围for循 环、auto关键字、新容器、列表初始化、标准线程库等 |
C++14 | 对C++11的扩展,主要是修复C++11中漏洞以及改进,比如:泛型的lambda表 达式,auto的返回值类型推导,二进制字面常量等 |
C++17 | 在C++11上做了一些小幅改进,增加了19个新特性,比如:static_assert()的文 本信息可选,Fold表达式用于可变的模板,if和switch语句中的初始化器等 |
C++20 | 自C++11以来最大的发行版,引入了许多新的特性,比如:模块(Modules)、协 程(Coroutines)、范围(Ranges)、概念(Constraints)等重大特性,还有对已有 特性的更新:比如Lambda支持模板、范围for支持初始化等 |
C++23 | 制定ing |
我们主要关注C++98和C++11两个发行版本,因为现在公司主流还是以这两个版本为标准。
3.关于C++的学习
- 多总结知识点,博客不能停,每学一节课,均需要写对应的博客进行记录
- 中后期画思维导图进行总结(可用XMind)
- 看C++书籍,前期可看《C++程序设计》这本书,用于入门;中期看《Effective C++》和《C++ Primer》,必看的两本书;后期可看《STL源码剖析》,注意这本书需要一定基础
- 勤刷题
在C语言中存在许多不足的地方,因此祖师爷对这些地方提出了解决办法,给出了一系列更加利于编程的语法,下面我将开始介绍。
一、关于命名空间
1.含义
在C/C++中,变量、函数和后面要学到的类都是大量存在的,这些变量、函数和类的名称将都存在于全局作用域中,可能会导致很多冲突。使用命名空间的目的是对标识符的名称进行本地化,以避免命名冲突或名字污染,namespace关键字的出现就是针对这种问题的。
列如看以下示例:
#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
#include<stdlib.h>
int rand = 1;
int main()
{
printf("%d\n", rand);
return 0;
}
程序报错:
其原因是rand为stdlib.h这个头文件里的一个方法,当我们定义Int rand为变量时,编译时,编译器会进行全局搜索,同时找到了stdlib.h里的rand以及我们定义的rand,这就造成了重定义了,这在c语言中时不允许的。
除了这种情况外,当我们面临命名冲突或多人进行项目时,也会形成命名冲突问题,简单来说,命名空间就是防止命名冲突。
2.定义
命名空间关键字为namespace,基本格式为:namespace+命名空间名字+{成员}。命名空间有以下三种情况:
//命名空间里成员可以为变量、函数、类型(结构体)
//1.正常的命名空间
namespace lmx{
int rand = 1;
int Add(int i, int j)
{
return i + j;
}
struct open
{
int k;
};
}
//2.嵌套命名空间
namespace oo {
int rand = 1;
namespace kk {
}
}
//3.同一个工程中,命名空间名相同会自动合并为一个命名空间
//以下命名空间会和第一个命名空间合并为一个。
namespace lmx {
int j = 1;
}
注意:一个命名空间就相当于一个作用域,其成员也属于该作用域内,如遇到情况3的合并命名空间中发现有相同的成员,这也会导致命名冲突问题。
4.使用
符号介绍::: 该符号称为作用限定符。
当我们需要访问命名空间的成员时,需要用作用限定符:
int main()
{
printf("%b\n", lmx::rand);
return 0;
}
但在现实开发中,这种方式比较麻烦,以下有两种方式可以不加作用限定符:
1.使用using将命名空间中某个成员引入(简称部分展开)
用于我们需要经常使用该成员,这种方式经常使用。
using lmx::rand;
int main()
{
printf("%b\n", rand);
return 0;
}
2.使用using namespace 命名空间名称 引入(简称全部展开)
命名空间内的成员都可以访问,不需要加作用限定符,但这种方式不可取,全部展开后相当于没有命名空间,容易造成命名冲突问题。
using namespace lmx;
int main()
{
printf("%d\n", rand);
return 0;
}
二、C++输入&输出
在C++中对于输入\输出有固定的符号,分别为<<(流插入)和>>(流提取)。
这里不过多介绍,我们只需知道在c++中输入\输出有以下特性:
//iostream头文件是c++中输入输出流文件
#include<iostream>
// std是C++标准库的命名空间名,C++将标准库的定义实现都放到这个命名空间中
using namespace std;
int main()
{
int k = 0;
//输入流-->相当于c语言中printf
cout << "Hello world!!!" << endl;
//输出流-->相当于c语言中scanf
cin >> k;
//特性:自动识别类型,不需要控制格式
int j = 2;
double k = 2.2;
cin >> j;
cin >> k;
cout << "j=" << j << endl;
cout << "k=" << k << endl;
return 0;
}
在日常练习中我们经常将名为std的命名空间全部展开,方便我们编写代码,但在实际开发中不可取,容易造成命名冲突。
三、缺省参数
1.缺省参数概念
缺省参数是声明或定义函数时为函数的参数指定一个缺省值。在调用该函数时,如果没有指定实参则采用该形参的缺省值,否则使用指定的实参。具体看以下例子:
//全缺省参数(参数全有值)
void Add(int k=1, int j = 1)
{
printf("%d", k + j);
}
//半缺省参数(部分参数有值)
void sub(int k, int j = 1)
{
printf("%d", k/j);
}
注意:1.半缺省参数必须从右往左依次来给出,不能间隔着给,如以下情况:
void Add(int k=1,int a, int j = 1)
{
printf("%d", k + j+ a);
}
2.缺省参数不能在函数声明和定义中同时出现,如以下情况:
//a.h
void Func(int a = 10);
// a.cpp
void Func(int a = 20)
{}
// 注意:如果生命与定义位置同时出现,恰巧两个位置提供的值不同,那编译器就无法确定到底该
用那个缺省值
对应这种情况,应为函数声明缺省,函数定义不缺省。
void Func(int a = 0)
{
cout<<a<<endl;
}
int main()
{
Func(); // 没有传参时,使用参数的默认值
Func(10); // 传参时,使用指定的实参
return 0;
}
3.缺省值必须是常量或者全局变量
五、函数重载
1.函数重载概念
函数重载:是函数的一种特殊情况,C++允许在同一作用域中声明几个功能类似的同名函数,这些同名函数的形参列表(参数个数 或 类型 或 类型顺序)不同,常用来处理实现功能类似数据类型
不同的问题。
简单来说就是函数的返回类型和函数名必须相同,参数不同。
具体有以下三种类型:
#include<iostream>
using namespace std;
// 1、参数类型不同
int Add(int left, int right)
{
cout << "int Add(int left, int right)" << endl;
return left + right;
}
double Add(double left, double right)
{
cout << "double Add(double left, double right)" << endl;
return left + right;
}
// 2、参数个数不同
void f()
{
cout << "f()" << endl;
}
void f(int a)
{
cont << "f(int a)" << endl;
}
// 3、参数类型顺序不同
void f(int a, char b)
{
cout << "f(int a,char b)" << endl;
}
void f(char b, int a)
{
cout << "f(char b, int a)" << endl;
}
int main()
{
Add(10, 20);
Add(10.1, 20.2);
f();
f(10);
f(10, 'a');
f('a', 10);
return 0;
}