C++初阶:初识C++入门篇(一)

✨✨小新课堂开课了,欢迎欢迎~✨✨

🎈🎈养成好习惯,先赞后看哦~🎈🎈

所属专栏:C++:由浅入深篇

小新的主页:编程版小新-CSDN博客

前言:正式进入知识点的学习之前,我们先来简单的了解一下C++吧。

一:C++的发展史 

C++的起源可以追溯到1979年,当时Bjarne Stroustrup(本贾尼·斯特劳斯特卢普,这个翻译的名字不同的地⽅可能有差异)在贝尔实验室从事计算机科学和软件工程的研究工作。面对项目中复杂的软件开发任务,特别是模拟和操作系统的开发工作,他感受到了现有语言(如C语言)在表达能力、可维护性和可扩展性方面的不足。

1983年,Bjarne Stroustrup在C语言的基础上添加了面向对象编程的特性,设计出了C++语言的雏形,此时的C++已经有了类、封装、继承等核心概念,为后来的面向对象编程奠定了基础。这⼀年该语言被正式命名为C++。

在随后的几年中,C++在学术界和工业界的应用逐渐增多。⼀些大学和研究所开始将C++作为教学和研究的首选语言,而一些公司也开始在产品开发中尝试使用C++。这一时期,C++的标准库和模板等特性也得到了进⼀步的完善和发展。

C++的标准化⼯作于1989年开始,并成立了⼀个ANSI和ISO(International Standards Organization)国际标准化组织的联合标准化委员会。1994年标准化委员会提出了第⼀个标准化草案。在该草案中,委员会在保持斯特劳斯特卢普最初定义的所有特征的同时,还增加了部分新特征。

在完成C++标准化的第⼀个草案后不久,STL(Standard Template Library)是惠普实验室开发的⼀系列软件的统称。它是由Alexander Stepanov、Meng Lee和David R Musser在惠普实验室⼯作时所开发出来的。在通过了标准化第⼀个草案之后,联合标准化委员会投票并通过了将STL包含到C++标准中的提议。STL对C++的扩展超出C++的最初定义范围。虽然在标准中增加STL是个很重要的决定,但也因此延缓了C++标准化的进程。

1997年11月14日,联合标准化委员会通过了该标准的最终草案。1998年,C++的ANSI/IS0标准被投入使用。

二:C++版本的更新 

现在大多数企业还是在沿用C++98和C++11这两个标准。 

三:C++的重要性 

3.1最新编程语言排行榜

3.2C++的就业方向 

C++的应用领域:服务器端、游戏(引擎)、机器学习引擎、音视频处理、嵌入式软件、电信设备、金融应用、基础库、操作系统、编译器、基础架构、基础工具、硬件交互等很多方面都有。
1.型系统软件开发。如编译器、数据库、操作系统、浏览器等等
2. 视频处理。常见的音视频开源库和方案有FFmpeg、WebRTC、Mediasoup、ijkplayer,音视频 开发最主要的技术栈就是C++。一般入职B站可能就搞这个。
3. PC客户端开发。一般是开发Windows上的桌面软件,比如WPS之类的,技术栈的话一般是C++和 QT,QT 是一个跨平台的 C++图形用户界面(Graphical User Interface,GUI)程序。
4. 服务端开发。各种大型应用网络连接的高并发后台服务。这块Java也比较多,C++主要用于些一对性能要求比较高的地方。如:游戏服务、流媒体服务、量化高频交易服务等
5. 游戏引擎开发。很多游戏引擎就都是使用C++开发的,游戏开发要掌握C++基础和数据结构,学习图形学知识,掌握游戏引擎和框架,了解引擎实现,引擎源代码可以学习UE4、Cocos2d-x等开源 引擎实现。
6. 嵌入式开发。嵌入式把具有计算能力的主控板嵌入到机器装置或者电子装置的内部,通过软件能够控制这些装置。比如:智能手环、摄像头、扫地机器人、智能音响、门禁系统、车载系统等,粗
略⼀点,嵌入式开发主要分为嵌入式应应和嵌入式驱动开发。
7. 机器学习引擎。机器学习底层的很多算法都是用C++实现的,上层用python封装起来。如果你只想准备数据训练模型,那么学会Python基本上就够了,如果你想做机器学习系统的开发,那么需要学会C++。
8. 测试开发/测试。每个公司研发团队,有研发就有测试,测试主要分为测试开发和功能测试,测试开发⼀般是使用一些测试工具(selenium、Jmeter等),设计测试用例,然后写一些脚本进行自动化测试,性能测试等,有些还需要自行开发一些测试用具。功能测试主要是根据产品的功能,设计测试用例,然后手动的方式进行测试。

四:C++的第一个程序

C++兼容C语言绝大多数的语法,所以C语言实现的hello world依旧可以运行,C++中需要把定义文件代码后缀改为.cpp,vs编译器看到是.cpp就会调用C++编译器编译,linux下要用g++编译,不再是gcc。
//test.cpp


#include<stdio.h>
int main()
{
   printf("hello world\n");
   return 0;
}
当然C++有⼀套自己的输入输出,严格说C++版本的hello world应该是这样写的。
// test.cpp

#include<iostream>
using namespace std;

int main()
{
   cout << "hello world\n" << endl;
   return 0;
}

 这里的std ,cout,endl等我们都看不懂,没关系,下面我们会依次讲解。

五:命名空间

5.1命名空间的价值

命名空间在C/C++中,变量、函数和后面要学到的类都是大量存在的,这些变量、函数和类的名称将都存在于全局作用域中,可能会导致很多冲突。使用命名空间的目的是对标识符的名称进行本地化,以避免命名冲突或名字污染,namespace关键字的出现就是针对这种问题的。
c语语项目类似下面程序这样的命名冲突是普遍存在的问题,C++引⼊namespace就是为了更好的解决这样的问题。
#include <stdio.h>
#include <stdlib.h>
int rand = 10;
int main()
{
	
	printf("%d\n", rand);
	return 0;
}

运行结果:

这里的报错其实就是 rand重定义。这里rand重定义的原因是rand与<stdlib.h>这个头文件中的rand函数同名,printf函数分不清是哪一个。更详细的解释我们放在命名空间的后面一些讲解。

5.2namespace(命名空间)的定义

1•  定义命名空间,需要使用到namespace关键字,后面跟命名空间的名字,然后接⼀对{}即可,{}中即为命名空间的成员。命名空间中可以定义变量/函数/类型等
#include <stdio.h>
#include <stdlib.h>
// 1. 正常的命名空间定义
// labi是命名空间的名字,一般开发中是用项目名字做命名空间名。
namespace labi
{
	// 命名空间中可以定义变量/函数/类型
	int rand = 10;

	int Add(int left, int right)
	{
		return left + right;
	}

	struct Node
	{
		struct Node* next;
		int val;
	};
}
int main()
{
	// 这里默认是访问的是全局的rand函数指针
	printf("%p\n", rand);

	// 这里指定labi命名空间中的rand
	printf("%d\n", labi::rand);//::是用来访问命名空间的

	return 0;
}
运行结果:

2• namespace本质是定义出一个域,这个域跟全局域,局部域各自独立,不同的域可以定义同名变量,所以下面的a不在冲突了。
#include <stdio.h>
#include <stdlib.h>

namespace labi
{
	//命名空间域
	int a = 10;
}

int main()
{
	//局部域
	int a = 1;
	//默认会在局部域和全局域中找,不会找命名空间
	printf("%d\n", a);

	printf("%d\n", labi::a);
}
运行结果:
3• C++中域有函数局部域,全局域,命名空间域,类域;域影响的是编译时语法查找⼀个变量/函数/
类型出处(声明或定义)的逻辑,所以有了域隔离,名字冲突就解决了。局部域和全局域除了会影响
编译查找逻辑,还会影响变量的声明周期,命名空间域和类域不影响变量声明周期
4• namespace只能定义在全局,当然他还可以嵌套定义
#include <stdio.h>
#include <stdlib.h>

// 命名空间可以嵌套
namespace haha
{
	//蜡笔
	namespace labi
	{
		int rand = 1;
		int Add(int left, int right)
		{
			return left + right;
		}
	}
	//小新
	namespace xiaoxin
	{
		int rand = 2;
		int Add(int left, int right)
		{
			return (left + right) * 10;
		}
	}
}
int main()
{
	printf("%d\n", haha::labi::rand);
	printf("%d\n", haha::xiaoxin::rand);
	printf("%d\n", haha::labi::Add(1, 2));
	printf("%d\n", haha::xiaoxin::Add(1, 2));
	return 0;
}

运行结果:

5• 项目工 程中多文件中定义的同名namespace会认为是一个namespace,不会冲突。
//stack.h
#pragma once
#include<stdio.h>
#include<stdlib.h>
#include<stdbool.h>
#include<assert.h>
namespace labi
{
	typedef int STDataType;
	typedef struct Stack
	{
		STDataType* a;
		int top;
		int capacity;
	}ST;
	void STInit(ST* ps, int n);
	
	void STPush(ST* ps, STDataType x);
	
}


//stack.cpp
#include"stack.h"
namespace labi
{
	void STInit(ST* ps, int n)
	{
		assert(ps);
		ps->a = (STDataType*)malloc(n * sizeof(STDataType));
		ps->top = 0;
		ps->capacity = n;
	}
	// 栈顶
	void STPush(ST* ps, STDataType x)
	{
		assert(ps);
		// 满了, 扩容
		if (ps->top == ps->capacity)
		{
			printf("扩容\n");
			int newcapacity = ps->capacity == 0 ? 4 : ps->capacity
				* 2;
			STDataType* tmp = (STDataType*)realloc(ps->a,
				newcapacity * sizeof(STDataType));
			if (tmp == NULL)
			{
				perror("realloc fail");
				return;
			}
			ps->a = tmp;
			ps->capacity = newcapacity;
		}
		ps->a[ps->top] = x;
		ps->top++;
	}
	
}

6• C++标准库都放在⼀个叫std(standard)的命名空间中。

5.3命名空间的使用

编译查找一个变量的声明/定义时,默认只会在局部或者全局查找,不会到命名空间里面去查找。所以 下面程序会编译报错。所以我们要使用命名空间中定义的变量/函数,有三种方式:
1• 指定命名空间访问,项目中推荐这种方式。
#include<stdio.h>
namespace labi
{
	int a = 0;
	int b = 1;
}
int main()
{
	// 编译报错:error C2065: “a”: 未声明的标识符
	//printf("%d\n", a);

	printf("%d\n", labi::a);
	return 0;
}

2• using将命名空间中某个成员展开,项目中经常访问的不存在冲突的成员推荐这种方式。
#include<stdio.h>
namespace labi
{
	int a = 0;
	int b = 1;
}


// using将命名空间中某个成员展开
using labi::b;
int main()
{
	printf("%d\n", labi::a);
	printf("%d\n", b);
	return 0;
}
3• 展开命名空间中全部成员,项目不推荐,冲突风险很大,日常小练习程序为了方便推荐使用。
#include<stdio.h>
namespace labi
{
	int a = 0;
	int b = 1;
}


// 展开命名空间中全部成员
using namespace labi;

int main()
{
	printf("%d\n", a);
	printf("%d\n", b);
	return 0;
}


六:C++的输入和输出

#include<iostream>
using namespace std;

int main()
{
   cout << "hello world\n" << endl;
   return 0;
}

现在我们就来解答我们遇到的第一个C++程序的吧。

<iostream> 是 Input Output Stream 的缩写,是标准的输入、输出流库,定义了标准的输入、输
出对象
std::cin 是 istream 类的对象,它主要面向窄字符(narrow characters (of type char))的标准输
入流。
std::cout 是 ostream 类的对象,它主要面向窄字符的标准输出流。
std::endl 是一个函数,流插入输出时,相当于插入一个换行字符加刷新缓冲区。(也可以这么理解endl==end line)
<<是流插入运算符,>>是流提取运算符。(C语言还用这两个运算符做位运算左移/右移)
使用C++输入输出更方便,不需要像printf/scanf输入输出时那样,需要手动指定格式,C++的输入输出可以 自动识别变量类型 (本质是通过函数重载实现的,这个以后会讲到),其实最重要的是
C++的流能更好的支持 自定义类型对象 的输入输出
IO流涉及类和对象,运算符重载、继承等很多面向对象的知识,这些知识我们还没有讲解,所以这里我们只能简单认识一下C++ IO流的用法,后面我们会有专门的来细节IO流库。
cout/cin/endl等都属于C++标准库,C++标准库都放在一个叫std(standard)的命名空间中,所以要通过命名空间的使用方式去用他们。
⼀般日常练习中我们可以using namespace std,实际项目开发中不建议using namespace std。(把这个命名空间全展开不安全)
这里我们没有包含<stdio.h>,也可以使用printf和scanf,其实是在包含<iostream>间接包含了。(vs系列编译器是这样的,其他编译器可能会报错)
下 面我们用几个示例加强理解吧。
示例一:
#include<iostream>
using namespace std;

int main()
{
	int i = 1234;
	int j = -1234;
	
	cout << i << endl;
	cout << j << endl;

    return 0;
}

运行结果:

示例二:

#include<iostream>
using namespace std;

int main()
{
	
	int a = 0;
	double b = 0.1;
	char c = 'x';

	cout << a << "             " << b << " " << c << "\n" << '\n' << endl;
	std::cout << a << " " << b << " " << c << std::endl;
    //cout 和 std::cout一个意思
	//自动识别类型

	return 0;
}

 运行结果:

示例三:

#include<iostream>
using namespace std;

int main()
{
	
	int a = 0;
	double b = 0;
	char c = 0;
	scanf("%d%lf", &a, &b);
	printf("%d %lf\n", a, b);

	// 可以自动识别变量的类型
	//cin >> a;
	//cin >> b >> c;
	cin >>a>> b >> c;
	cout << a << endl;
	cout << b << " " << c << endl;

	return 0;
}

运行结果: 

七:缼省参数

缺省参数是声明或定义函数时为函数的参数指定一个缺省值。在调用该函数时,如果没有指定实参则采用该形参的缺省值,否则使用指定的实参,缺省参数分为全缺省和半缺省参数。(有些地方把缺省参数也叫默认参数)
全缺省就是全部形参给缺省值,半缺省就是部分形参给缺省值 C++规定半缺省参数必须从右往左依次连续缺省,不能间隔跳跃给缺省值
带缺省参数的函数调用,C++规定必须从左到右依次给实参,不能跳跃给实参
函数声明和定义分离时,缺省参数不能在函数声明和定义中同时出现,规定必须函数声明给缺省
值。
示例一:
#include <iostream>
#include <assert.h>
using namespace std;
void Func(int a = 0)
{
    cout << a << endl;
}
int main()
{
    Func(); // 没有传参时,使⽤参数的默认值
    Func(10); // 传参时,使⽤指定的实参
    return 0;
}

运行结果:

示例二:

#include <iostream>

using namespace std;

// 全缺省
void Func1(int a = 10, int b = 20, int c = 30)
{
	cout << "a = " << a << endl;
	cout << "b = " << b << endl;
	cout << "c = " << c << endl << endl;
}

// 半缺省
//从右往左依次缼省,不得跳跃
void Func2(int a, int b = 10, int c = 20)
{
	cout << "a = " << a << endl;
	cout << "b = " << b << endl;
	cout << "c = " << c << endl << endl;
}

int main()
{
	Func1();
	Func1(1);
	Func1(1, 2);
	//从左往右依次给参数,不得跳跃
	//Func1(1, ,3)这种写法错误
	Func1(1, 2, 3);
	Func2(100);
	Func2(100, 200);
	Func2(100, 200, 300);
	return 0;
}

运行结果:

示例三: 

// Stack.h
#include <iostream>
#include <assert.h>

using namespace std;

typedef int STDataType;

typedef struct Stack
{
	STDataType* a;
	int top;
	int capacity;
}ST;


//声明
void STInit(ST* ps, int n = 4);


// Stack.cpp

#include"Stack.h"

// 缺省参数不能声明和定义同时给
void STInit(ST* ps, int n)
{
	assert(ps && n > 0);
	ps->a = (STDataType*)malloc(n * sizeof(STDataType));
	ps->top = 0;
	ps->capacity = n;
}

#include"Stack.h"

int main()
{
	ST s1;
	STInit(&s1);
	// 确定知道要插⼊1000个数据,初始化时⼀把开好,避免扩容
	ST s2;
	STInit(&s2, 1000);
	return 0;
}

八:函数重载

C++支持在同一作用域中出现同名函数,但是要求这些同名函数的形参不同,可以是参数个数不同或者类型不同。这样C++函数调用就表现出了多态行为,使用更灵活。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)
{
	cout << "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;
}


// 返回值不同不能作为重载条件,因为调用时也无法区分
//void fxx()
//{}
//
//int fxx()
//{
// return 0;
//}
// 下面两个函数构成重载
// f()但是调用时,会报错,存在歧义,编译器不知道调用谁

void f1()
{
	cout << "f()" << endl;
}

void f1(int a = 10)
{
	cout << "f(int a)" << endl;
}

int main()
{
	Add(10, 20);
	Add(10.1, 20.2);
	f();
	f(10);
	f(10, 'a');
	f('a', 10);
	return 0;
}

相关推荐

  1. C++

    2024-07-15 04:24:04       54 阅读
  2. C++模板

    2024-07-15 04:24:04       43 阅读

最近更新

  1. docker php8.1+nginx base 镜像 dockerfile 配置

    2024-07-15 04:24:04       66 阅读
  2. Could not load dynamic library ‘cudart64_100.dll‘

    2024-07-15 04:24:04       70 阅读
  3. 在Django里面运行非项目文件

    2024-07-15 04:24:04       57 阅读
  4. Python语言-面向对象

    2024-07-15 04:24:04       68 阅读

热门阅读

  1. 如何评价一个AI系统

    2024-07-15 04:24:04       21 阅读
  2. 查找运行中 sql中bind variable value 绑定变量值

    2024-07-15 04:24:04       22 阅读
  3. appium 实战问题 播放视频时无法定位到元素

    2024-07-15 04:24:04       28 阅读
  4. Django模板语言(简略教程)

    2024-07-15 04:24:04       25 阅读
  5. std::async和std::future异步编程

    2024-07-15 04:24:04       23 阅读
  6. C++智能指针

    2024-07-15 04:24:04       20 阅读