【C++】踏上C++学习之旅(一):初识C++和命名空间

news2024/12/24 3:24:05

动图

文章目录

  • 前言
  • 1. 初识C++
  • 2. C++的发展阶段
  • 2. 命名空间
    • 2.1 为什么要有命名空间?
    • 2.2 命名空间的语法
    • 2.3 命名空间的原理
    • 2.4 使用命名空间的三种方式
      • 2.4.1 加命名空间名称及作用域限定符( :: )
      • 2.4.2 使用using关键字将命名空间中某个成员 引入
      • 2.4.3 使用using namespace 命名空间名 引入
  • 3. 简单了解C++的输入和输出

前言

本文是正式踏上C++学习之旅的第一篇文章,也是我分享C++笔记的第一篇文章。在这篇文章中,我会给大家介绍C++的发展历史,让大家更好从C语言过渡到C++,也会让大家认识到为什么C++能够兼容C语言的语法。

光是讲解C++的历史那可就太无趣了,所以在本文中我还会给大家加一点料 —— “命名空间”,以及如何高效的使用C++中命名空间。

还会教大家如何用C++的方式,输出"Hello World"。

哈哈哈

1. 初识C++

C语言是结构化和模块化的语言,适合处理较小规模的程序。对于复杂的问题,规模较大的程序,需要高度的抽象和建模时,C语言则不合适。为了解决软件危机, 20世纪80年代, 计算机界提出了OOP(objectoriented programming:面向对象)思想,支持面向对象的程序设计语言应运而生。所以我们经常说到C++是面向对象的语言,而C语言是面向过程的语言。

1982年,Bjarne Stroustrup博士在C语言的基础上引入并扩充了面向对象的概念,发明了一种新的程序语言。为了表达该语言与C语言的渊源关系,命名为C++。因此:C++是基于C语言而产生的,它既可以进行C语言的过程化程序设计,又可以进行以抽象数据类型为特点的基于对象的程序设计,还可以进行面向对象的程序设计。

请大家记住C++诞生的时间(1982年)以及发明C++的大佬 —— “本贾尼”!

2. C++的发展阶段

作为了解就好,但是也要知道我们现在是在用C++版本是多少。

阶段内容
C with classes类及派生类、公有和私有成员、类的构造和析构、友元、内联函数、赋值运算符重载等
C++1.0添加虚函数概念,函数和运算符重载,引用、常量等
C++2.0更加完善支持面向对象,新增保护成员、多重继承、对象的初始化、抽象类、静态成员以及const成员函数
C++3.0进一步完善,引入模板,解决多重继承产生的二义性问题和相应构造和析构的处理
C++98C++标准第一个版本,绝大多数编译器都支持,得到了国际标准化组织(ISO)和美国标准化协会认可,以模板方式重写C++标准库,引入了STL(标准模板库)
C++03C++标准第二个版本,语言特性无大改变,主要:修订错误、减少多异性
C++05C++标准委员会发布了一份计数报告(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明确的对象参数(Deducing this)、if consteval、多维下标运算符、内建衰减复制支持、标记不可达代码(std::unreachable)、平台无关的假设([[assume]])、命名通用字符转义、扩展基于范围的 for 循环中临时变量的生命周期、constexpr 增强、简化的隐式移动、静态运算符 static operator[] 以及类模板参数推导

C++还在不断地向后发展。但是现在公司主流的是用的还是C++98和C++11,等大家以后工作时可以慢慢钻研C++的新特性,现在这需要我们熟练的掌握C++98和C++11这两个标准即可。

我们现在学习阶段大都接触到的也就是这两种标准(C++11和C++98)。

哈哈哈

2. 命名空间

2.1 为什么要有命名空间?

请大家看一下下面的代码:

#include<stdio.h>

int rand = 0;
int main()
{
	int rand = 10;
	printf("%d\n",rand);
	return 0;
}

上面的代码会不会报错?相信掌握C语言语法的读者就会说,上面的代码是可以正常编译通过的。没错,上面的代码的确是没有任何问题的。

那如果我将上述的代码做了一点改变,代码还能正常编译过去吗?

#include<stdio.h>
#include<stdlib.h>
int rand = 0;
int main()
{
	int rand = 10;
	printf("%d\n",rand);
	return 0;
}

如果你们自己去测试的话,显然会出现编译错误。
编译错误

这是什么原因呢?
编译器说rand重定义,而且错误是我们在引用stdlib.h的头文件之后才出现的。到这里我们就意识到了有个rand的变量名或者时函数名,而我们知道一个.c/.cpp的源文件在编译阶段的预处理阶段会把头文件的内容给展开,所以就会出现rand重定义了。

这个问题在C语言上只能是要你改变这个变量名了。C++就能够解决这个问题,即使你不更改变量名,编译器也不会报错,这个C++的利器就是命名空间

为了让大家对命名空间的这个新事物引起更高的重视,我来给大家举个生活中实际例子:

比如现在有一个互联网公司,这个公司最近准备研发一个项目,老板就把项目就分配给了一个小组,而小组里面有两人小明和小刚负责分别负责这个项目的两个模块。他们两个写啊写啊,终于有一天他们俩将各自写的项目都提交了上去,编译一下却出现错误,经过检查发现他们两个项目的变量名有很多是重叠了,这个会出现命名冲突的问题。如果他们是用C语言来写的话,那必定有一方得是改变变量命名,那两个人肯定都不愿意改的。如果用C++的命名空间的话,就可以完美避开这个问题了。

好了,在讲完命名空间的重要性之后,我们就得认识一下命名空间的用法以及底层的原理!

2.2 命名空间的语法

namespace 命名空间名
{
	内容
}

下面我来一遍做展示,一遍拓展:

  1. 这个是我们进行正常的命名空间定义:
namespace test
{
	int rand = 10;
	int Add(int x, int y)
	{
		return x+y;
	}

	struct Node
	{
		int data;
		struct Node* next;
	}
}

🍉我们不仅可以在命名空间定义并初始化变量,还可以进行对函数的定义,结构体的定义等。

  1. 命名空间可以嵌套:
namespace N1
{
	int a;
	int b;
	int Add(int left, int right)
 	{
     	return left + right;
 	}
	namespace N2
 	{
     	int c;
     	int d;
     	int Sub(int left, int right)
     	{
     	    return left - right;
     	}
 	}
}

🍉可以看到我们中命名空间去嵌套另一个命名空间。

  1. 同一个工程中允许不同的文件出现名称相同的命名空间,但是最后编译器会将不同文件相同名称的命名空间给合并到一起:
//这个是test.h文件里面的命名空间
namespace N1
{
	int Mul(int left, int right)
 	{
    	 return left * right;
	}
}

//这个是test.cpp文件里面的命名空间
namespace N1
{
	int a;
	int b;
	int Add(int left, int right)
	 {
	     return left + right;
	 }
	namespace N2
	{
	     int c;
 	     int d;
	     int Sub(int left, int right)
     	{
         	return left - right;
     	}
 	}
}

经过编译器的编译之后,最后的合并的结果就是:

namespace N1
{
	int Mul(int left, int right)
 	{
    	 return left * right;
	}
	int a;
	int b;
	int Add(int left, int right)
	 {
	     return left + right;
	 }
	namespace N2
	{
	     int c;
 	     int d;
	     int Sub(int left, int right)
     	{
         	return left - right;
     	}
 	}
}

2.3 命名空间的原理

提到命名空间,我们就不得不提另一个概念"域"。

想必大家或多或少都会在C语言中听过"作用域"(全局域、局部域)这个名词。这个就是"域"中的一种,在C++中还有命名空间域、类域等等。而我们现在说讲的命名空间,它的实质就是一种命名空间域。

那可能有的读者会问,"域"是个什么东西?
那我们可以先从我们熟悉的入手,全局域和局部域。我们都知道在给全局变量和局部变量去相同的变量名时,程序是不会报错的,这个就是"域"的作用。我们可以把"域"想象成一面墙,被这面的墙隔开的事物互不干扰,你干你的事,我刚我的事。
讲到这里,我相信你已经对命名空间域已经有感觉了。我们也可以把命名空间域看作是一面墙,将局部域与全局域给隔开了。在这个域里面有自己独自维护的变量。

🍉所以我们可以总结一下:命名空间是解决全局变量与头文件的命名冲突问题,或者是解决同一个工程项目中不同模块之间的命名冲突问题。

2.4 使用命名空间的三种方式

我们讲解了命名空间的原理,那命名空间里面的成员我们该怎么引用呢?比如:

namespace test
{
 	// 命名空间中可以定义变量/函数/类型
 	int a = 0;
	 int b = 1;
 	int Add(int left, int right)
 	{
 		return left + right;
 	}
 	struct Node
 	{
 		struct Node* next;
 		int val;
 	};
}

int main()
{
 	// 编译报错:error C2065: “a”: 未声明的标识符
 	printf("%d\n", a);
	return 0;
}

2.4.1 加命名空间名称及作用域限定符( :: )

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

2.4.2 使用using关键字将命名空间中某个成员 引入

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

这种方式建议使用!!!

2.4.3 使用using namespace 命名空间名 引入

using  namespace test;
int main()
{
 	printf("%d\n", test::a);
 	printf("%d\n", b);
 	Add(10,20);
	return 0;
}

🍉注意:使用这个方法时是有风险的(这个命名空间里面有着和全局变量一样的变量名),所以我们在平时进行练习或比赛的时候使用即可。


3. 简单了解C++的输入和输出

我们再学一门新的语言时,往往会都会干一件事,就是在屏幕上输出"Hello World"。
所以这里我们就简单认识一下C++的输入和输出。

#include<iostream>
// std是C++标准库的命名空间名,C++将标准库的定义实现都放到这个命名空间中
using namespace std;
int main()
{
	cout<<"Hello world!!!"<<endl;
	return 0;
}

说明:
1. 使用cout标准输出对象(控制台)和cin标准输入对象(键盘)时,必须包含< iostream >头文件以及按命名空间使用方法使用std。
2. cout和cin是全局的流对象,endl是特殊的C++符号,表示换行输出他们都包含在包含< iostream >头文件中。
3. <<是流插入运算符,>>是流提取运算符。
4. 使用C++输入输出更方便,不需要像printf/scanf输入输出时那样,需要手动控制格式。
C++的输入输出可以自动识别变量类型。
5. 实际上cout和cin分别是ostream和istream类型的对象,>>和<<也涉及运算符重载等知识,这些知识我们我们后续才会学习,所以我们这里只是简单学习他们的使用。

注意:早期标准库将所有功能在全局域中实现,声明在.h后缀的头文件中,使用时只需包含对应
头文件即可,后来将其实现在std命名空间下,为了和C头文件区分,也为了正确使用命名空间,
规定C++头文件不带.h;旧编译器(vc 6.0)中还支持<iostream.h>格式,后续编译器已不支持,因
此推荐使用+std的方式。

#include <iostream>
using namespace std;
int main()
{
   int a = 10;
   double b = 3.1415;
   char c = 'l';
     
   // 可以自动识别变量的类型
   cin>>a;
   cin>>b>>c;
     
   cout<<a<<endl;
   cout<<b<<" "<<c<<endl;
   return 0;
}

🍉最后在声明一点,std命名空间的使用惯例:
std是C++标准库的命名空间,如何展开std使用更合理呢?

  1. 在日常练习中,建议直接using namespace std即可,这样就很方便。
  2. using namespace std展开,标准库就全部暴露出来了,如果我们定义跟库重名的类型/对象/函数,就存在冲突问题。该问题在日常练习中很少出现,但是项目开发中代码较多、规模大,就很容易出现。所以建议在项目开发中使用,像std::cout这样使用时指定命名空间 + using std::cout展开常用的库对象/类型等方式。

到这里本文就结束了,如果觉得文章写得还不错的话,麻烦给偶点个赞吧!!!

hahaha

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2212723.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

注意力机制篇 | 清华大学提出Focused Linear Attention取代Self-Attention成为ViT的新宠

前言:Hello大家好,我是小哥谈。Focused Linear Attention(聚焦线性注意力)是一种用于视觉Transformer模型的注意力机制,旨在提高效率和表现力,它解决了传统线性注意力方法的两个主要问题:聚焦能力和特征多样性。🌈 目录 🚀1.基础概念 🚀2.网络结构 🚀3.…

网络安全学习路线-适合入门小白

首先说明&#xff0c;我是一名CTF的web手&#xff0c;这是我自己亲身学习网络安全的路线&#xff0c;希望能够帮到大家&#xff0c;我虽然不是大牛&#xff0c;但我也希望能够帮助一些网安小白找到自己学习的方向&#xff0c;后面有就业的详细安全技术要求&#xff0c;如果真想…

大数据-170 Elasticsearch 云服务器三节点集群搭建 测试运行

点一下关注吧&#xff01;&#xff01;&#xff01;非常感谢&#xff01;&#xff01;持续更新&#xff01;&#xff01;&#xff01; 目前已经更新到了&#xff1a; Hadoop&#xff08;已更完&#xff09;HDFS&#xff08;已更完&#xff09;MapReduce&#xff08;已更完&am…

基于知识图谱的宁夏非遗问答系统

八维视角探索宁夏非遗文化——基于知识图谱的非遗问答系统 作为一名程序员&#xff0c;能将大数据与文化传承结合&#xff0c;赋予历史新的生命&#xff0c;是件多么振奋的事&#xff01;今天给大家介绍的是一款基于知识图谱技术的宁夏非物质文化遗产问答系统。无论你是学术研…

数字化转型最佳实践与实施技巧:理论指导与企业应用路径

数字化转型中的最佳实践与实施技巧 企业在实施数字化转型时&#xff0c;面对的最大挑战之一是如何将理论转化为实际可操作的行动。成功的转型不仅依赖于新技术的引入&#xff0c;还涉及如何确保架构蓝图与业务目标一致&#xff0c;如何在确保合规的基础上进行创新&#xff0c;…

重磅!博世「入局」Chiplets,汽车芯片格局或迎来新「拐点」

汽车行业似乎并不想重复PC、手机时代的老路。 在过去几年时间里&#xff0c;由于消费类芯片巨头&#xff08;包括英伟达、高通、AMD、英特尔等&#xff09;大举进军汽车行业&#xff0c;导致传统Tier1和汽车芯片厂商逐步失去了市场控制权。如今&#xff0c;chiplets技术或许将重…

PHP实现OPENSSL的EVP_BytesToKey

使用PHP和nodejs进行通讯时候遇到双方加解密结果不一致的问题。 注意到crypto.createCipher(algorithm, password[, options])方法有如下的提示。 The implementation of crypto.createCipher() derives keys using the OpenSSL function EVP_BytesToKey with the digest alg…

Springboot整合抖音小程序获取access-token图片检测V3

抽取配置文件 appId以及secret需要自行在抖音开放平台获取 dy:appId: ttb0xxxxxsecret: 12a19a426xxxxxxxxxxxxx获取access-token 参照文档我们调用此接口需要先获取access-token 获取access-token官方文档地址 注意事项 client_token 的有效时间为 2 个小时&#xff0c;重复获…

基于Matlab使用蚁群算法寻找最优路径

基于Matlab使用蚁群算法寻找最优路径 与Dijkstra算法使用相同的地图。 每只蚂蚁都从起点出发&#xff0c;直到抵达终点。这与Example5_1.m 中解决旅行商问题不一样&#xff0c;旅行商问题中每一代的蚂蚁都是随机从一个节点出发。 文件说明 Example5_1.m 简单对参考资料2中的…

重启Windows远程的复制粘贴功能

有些时候远程Windows电脑偶尔会出现复制粘贴失效的情况 打开任务管理器&#xff0c;进程搜索RDP 剪贴板监视程序右键关闭任务。 因为远程剪切板程序位于C:\Windows\System32&#xff0c;所以直接winr输入rdpclip.exe执行即可启动。

Java项目实战II基于Java的医院急诊系统设计与实现(开发文档+源码+数据库)

目录 一、前言 二、技术介绍 三、系统实现 四、文档参考 五、核心代码 六、源码获取 全栈码农以及毕业设计实战开发&#xff0c;CSDN平台Java领域新星创作者&#xff0c;专注于大学生项目实战开发、讲解和毕业答疑辅导。获取源码联系方式请查看文末 一、前言 在现代医疗…

提升正则表达式性能:全面解析Golang regexp/syntax包

提升正则表达式性能&#xff1a;全面解析Golang regexp/syntax包 介绍基本概念正则表达式简介regexp/syntax包的作用 regexp/syntax包的结构核心组件结构详解ParserRegexpOpInstProg 使用Parser解析正则表达式解析正则表达式AST的结构 分析解析后的正则表达式树AST节点类型分析…

Linux下Git操作

一、基本命令 1、创建 git 目录&#xff08;工作区&#xff09; mkdir gitcode 2、创建本地仓库&#xff0c;生成 .git 隐藏目录 git init 3、设置配置项 git config user.name "xxx" git config user.email "....." 4、查看配置项 git config -l …

将SpringBoot的Maven项目打成jar包和war包

先需要明确的是&#xff0c;该项目打包的形态是可执行的jar包&#xff0c;还是在tomcat下运行的war包。 springboot自带的maven打包 1.创建一个springboot web项目 1.api控制层HelloWorld.java RestController RequestMapping("/hello") public class HelloWorld …

SpringBoot基础(五):集成JUnit5

SpringBoot基础系列文章 SpringBoot基础(一)&#xff1a;快速入门 SpringBoot基础(二)&#xff1a;配置文件详解 SpringBoot基础(三)&#xff1a;Logback日志 SpringBoot基础(四)&#xff1a;bean的多种加载方式 SpringBoot基础(五)&#xff1a;集成JUnit5 目录 一、JUnit…

使用dotnet-counters和dotnet-dump 分析.NET Core 项目内存占用问题

在.NET Core 项目部署后&#xff0c;我们往往会遇到内存占用越来越高的问题&#xff0c;但是由于项目部署在Linux上&#xff0c;因此无法使用VS的远程调试工具来排查内存占用问题。那么这篇文章我们大家一起来学习一下如何排查内存占用问题。 首先&#xff0c;我们来看一下应用…

Python | Leetcode Python题解之第478题在圆内随机生成点

题目&#xff1a; 题解&#xff1a; class Solution:def __init__(self, radius: float, x_center: float, y_center: float):self.xc x_centerself.yc y_centerself.r radiusdef randPoint(self) -> List[float]:u, theta random.random(), random.random() * 2 * mat…

rancher hello-world

创建一个Deployment, 只填名称和容器镜像rancher/hello-world 成功后: 查看日志 结果&#xff1a; 部署了工作负载。这个过程可能需要几分钟完成。 当您的工作负载部署完成后&#xff0c;它的状态将变为Active&#xff0c;您可以从项目的工作负载页面查看工作负载当前的状态…

Golang | Leetcode Golang题解之第475题供暖器

题目&#xff1a; 题解&#xff1a; func findRadius(houses, heaters []int) (ans int) {sort.Ints(houses)sort.Ints(heaters)j : 0for _, house : range houses {dis : abs(house - heaters[j])for j1 < len(heaters) && abs(house-heaters[j]) > abs(house-…

threejs 前言

Three.js 中文官方网站 一、项目结构 二、相关开源库 下面表格列举了一些Three.js相关的开源库。