【C++初阶】第一站:C++入门基础(上) -- 良心详解-1

简介: 【C++初阶】第一站:C++入门基础(上) -- 良心详解-1

什么是C++

 

C语言是结构化和模块化的语言,适合处理较小规模的程序。对于复杂的问题,规模较大的程序,需要高度的抽象和建模时,C语言则不合适。为了解决软件危机, 20世纪80年代, 计算机界提出了OOP(object oriented programming:面向对象)思想,支持 面向对象 的程序设计语言应运而生。
      1982年,Bjarne Stroustrup博士在C语言的基础上引入并扩充了面向对象的概念,发明了一种新的程序语言。为了表达该语言与C语言的渊源关系,命名为C++。因此:C++是基于C语言而产生的,它既可以进行C语言的过程化程序设计,又可以进行以抽象数据类型为特点的基于对象的 程序设计,还可以进行面向对象的程序设计。

C++的发展史

        1979年,贝尔实验室的本贾尼等人试图分析unix内核的时候,试图将内核模块化,于是在C

语言的基础上进行扩展,增加了类的机制,完成了一个可以运行的预处理程序,称之为C with

classes。

        语言的发展就像是练功打怪升级一样,也是逐步递进,由浅入深的过程。我们先来看下C++的历史版本。

5b9d66d1ae564e949598a082d7e3d121.png


        C++还在不断的向后发展。但是:现在公司主流使用还是C++98和C++11,所有大家不用追求最新,重点将C++98和C++11掌握好,等工作后,随着对C++理解不断加深,有时间可以去琢磨下更新的特性。

C++关键字(C++98)

C++总计63个关键字,C语言32个关键字

ps:下面我们只是看一下C++有多少关键字,不对关键字进行具体的讲解。后面我们学到以后再

细讲。

5fa33652490f49429aefd02eda0b1392.png

C语言的关键字:


bf4c12f4c00249eebcca551e432b5f3f.png


命名空间

        在C/C++中,变量、函数和后面要学到的类都是大量存在的,这些变量、函数和类的名称将都存在于全局作用域中,可能会导致很多冲突。使用命名空间的目的是对标识符的名称进行本地化,

以避免命名冲突或名字污染,namespace关键字的出现就是针对这种问题的

举例:

#include<stdio.h>
#include<stdlib.h>
//命名冲突 
int rand = 10;
// C语言没办法解决类似这样的命名冲突问题,所以C++提出了namespace来解决
int main()
{
  printf("%d\n",rand);
// 编译后后报错:error C2365: “rand”: 重定义;以前的定义是“函数”
  return 0;
}

执行:



7b451118fd824e6a9ee4fbe1646e0e5e.png

解释:


     

在C语言中,rand是一个库函数,用于生成伪随机数。然而,在该代码中,rand被重新定义为一个整数变量并赋值为10。这导致命名冲突。

要解决这个问题,你可以考虑以下两种方法之一:


改变变量名:将变量名rand更改为其他名称,以避免与库函数rand发生冲突。
使用C++:将代码保存为以.cpp为扩展名的文件,并使用命名空间来解决命名冲突。

命名空间定义

       定义命名空间,需要使用到namespace关键字,后面跟命名空间的名字,然后接一对{}即可,{}中即为命名空间的成员。

1. 正常的命名空间定义

1.1命名空间中可以定义变量/函数/类型(结构体)

// 1. 正常的命名空间定义
namespace bit
{
    // 命名空间中可以定义变量/函数/类型
   int rand = 10;
 
   int Add(int left, int right)
   {
     return left + right;
   }
 
   struct Node
   {
     struct Node* next;
     int val;
   };
}

1.2命名空间可以嵌套


namespace zzc
{
  //命令空间中可以定义变量/函数/类型
  int rand = 10;
  int Add(int left, int right)
  {
  return left + right;
  }
  struct Node
  {
  struct Node* next;
  int val;
  };
  namespace zzc1
  {
  int rand = 1;
  }
}
int Add(int left, int right)
{
  return (left + right) * 10;
}
int main()
{
  printf("%d\n",zzc::rand);
  printf("%d\n", zzc::zzc1::rand);//命名空间的嵌套
  printf("%d\n",Add(1,2));
    printf("%d\n",zzc::Add(1,2));
  struct zzc::Node node;//命名空间里面的结构体类型创建变量
  return 0;
}


代码执行:


d2c71096b8dc4245b31d2771529cddba.png


1.3同一个工程中允许存在多个相同名称的命名空间,编译器最后会合成同一个命名空间中

 

注意:一个命名空间就定义了一个新的作用域 ,命名空间中的所有内容都局限于该命名空间中
#include<stdio.h>
#include<iostream> 
#include<stdlib.h>
//Stack.h
namespace zzc
{
  void StackInit()
  {
  cout << "void StackInit()" << endl;
  }
  namespace zzc1
  {
  int rand = 0;
  }
}
//Queue.h
namespace zzc
{
  void QueueInit()
  {
  cout << "void QueueInit()" << endl;
  }
  namespace zzc
  {
  int rand = 1;
  }
}
using std::cout;
using std::endl;
#include"Stack.h"
#include"Queue.h"
int main()
{
  //命名空间的合并
  zzc::StackInit();
  zzc::QueueInit();
  return 0;
}

执行:



412340db55794997b806a8488f426a76.png

命名空间使用

命名空间中成员该如何使用呢?比如:

namespace bit
{
 // 命名空间中可以定义变量/函数/类型
 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;
}


执行:


676cb440b9314f7a88e7eff69c187b66.png


命名空间的使用有三种方式:

1.加命名空间名称及作用域限定符

       在C++中,::被称为作用域限定符(Scope Qualifier)。作用域限定符用于指定特定的作用域,并在该作用域中查找标识符。


       通过使用作用域限定符,你可以在命名空间、类、结构体、枚举等作用域中精确地引用特定的成员或标识符。


       作用域限定符的语法是namespace(命名空间zzc)::identifier或 class(类名)::identifier,其中namespace是命名空间的名称(zzc),class是类的名称,identifier是成员或标识符的名称。


namespace zzc
{
  //命令空间中可以定义变量/函数/类型
  int rand = 10;
}

执行:


26a496ee64da4c748af2b813c3260887.png


2.使用using将命名空间中某个成员引入

   

       部分展开(授权) -- 比如下面允许(授权)使用者去zzc里面的Add去访问和引用。

图解:


d3339b4db30f470bbdf96d50cfd91b08.png

代码实现:

namespace zzc
{
  //命令空间中可以定义变量/函数/类型
  int rand = 10;
  int Add(int left, int right)
  {
  return left + right;
  }
  struct Node
  {
  struct Node* next;
  int val;
  };
    //嵌套
  namespace zzc1
  {
  int rand = 1;
  }
}
//部分展开(授权)
using zzc::Add;
int main()
{
  printf("%d\n",zzc::Add(1,2));
  printf("%d\n",Add(1,2));
}

3.使用using namespace 命名空间名称引入

       全部展开(授权)--展开命名空间,意思是把所有墙都给它拆掉,把命名空间里面所有内容展开,默认是找全局的,那就没有区别之分了,所以很容易引起命名冲突,是一件很危险的事情


   

在使用using namespace时,存在一些潜在的风险和注意事项,因此需要谨慎使用。以下是一些相关的考虑因素:
命名冲突:如果你使用using namespace引入了多个命名空间,而这些命名空间中有相同名称的成员,就会导致命名冲突。这可能会使代码难以理解,且不明确引用的成员可能会导致错误的调用。
命名空间污染:使用using namespace会将整个命名空间的所有成员引入当前作用域,这可能导致命名空间的成员与当前作用域中的其他标识符发生冲突。这可能会引入不必要的歧义和错误。
可读性和维护性:在代码中广泛使用using namespace可能会降低代码的可读性和维护性。其他开发人员可能不熟悉引入的命名空间,并且很难追踪代码中使用的具体成员的来源。

在展开namespace之前运行:


       由于rand函数是头文件stdlib.h里面的内容,所以不初始化的时候是随机值。(rand函数的函数名就是函数的地址)

df7603e0e7744c3bae95f3721d14ebfe.png



在展开zzc这个namespace之后:


#include<stdlib.h>
using namespace zzc;

       可以发现,rand的打印不明确,这是为什么呢?原因是,命名空间zzc相当于用一道墙把命名空间域里面的内容和全局变量隔离起来了,现在使用using namespace关键字,相当于把墙拆了,就引起了名字冲突 --  zzc里面rand函数与头文件里面的rand函数的冲突。


87dc265630a74b138eb640357f145189.png


总结:还是指定最安全,不要把"墙"拆掉(但是指定需要大量用到,如果觉得命名空间zzc::使用次数过多,那么请使用上面第2点的部分展开)




8abaeb4d2cf6417ca652e6e7295d8d54.png


【C++初阶】第一站:C++入门基础(上) -- 良心详解-2

https://developer.aliyun.com/article/1456955

相关文章
|
6月前
|
存储 安全 编译器
c++入门
c++作为面向对象的语言与c的简单区别:c语言作为面向过程的语言还是跟c++有很大的区别的,比如说一个简单的五子棋的实现对于c语言面向过程的设计思路是首先分析解决这个问题的步骤:(1)开始游戏(2)黑子先走(3)绘制画面(4)判断输赢(5)轮到白子(6)绘制画面(7)判断输赢(8)返回步骤(2) (9)输出最后结果。但对于c++就不一样了,在下五子棋的例子中,用面向对象的方法来解决的话,首先将整个五子棋游戏分为三个对象:(1)黑白双方,这两方的行为是一样的。(2)棋盘系统,负责绘制画面。
99 0
|
10月前
|
存储 缓存 C++
C++ 容器全面剖析:掌握 STL 的奥秘,从入门到高效编程
C++ 标准模板库(STL)提供了一组功能强大的容器类,用于存储和操作数据集合。不同的容器具有独特的特性和应用场景,因此选择合适的容器对于程序的性能和代码的可读性至关重要。对于刚接触 C++ 的开发者来说,了解这些容器的基础知识以及它们的特点是迈向高效编程的重要一步。本文将详细介绍 C++ 常用的容器,包括序列容器(`std::vector`、`std::array`、`std::list`、`std::deque`)、关联容器(`std::set`、`std::map`)和无序容器(`std::unordered_set`、`std::unordered_map`),全面解析它们的特点、用法
C++ 容器全面剖析:掌握 STL 的奥秘,从入门到高效编程
|
9月前
|
存储 分布式计算 编译器
C++入门基础2
本内容主要讲解C++中的引用、inline函数和nullptr。引用是变量的别名,与原变量共享内存,定义时需初始化且不可更改指向对象,适用于传参和返回值以提高效率;const引用可增强代码灵活性。Inline函数通过展开提高效率,但是否展开由编译器决定,不建议分离声明与定义。Nullptr用于指针赋空,取代C语言中的NULL。最后鼓励持续学习,精进技能,提升竞争力。
|
存储 安全 编译器
【C++打怪之路Lv1】-- 入门二级
【C++打怪之路Lv1】-- 入门二级
133 0
|
自然语言处理 编译器 C语言
【C++打怪之路Lv1】-- C++开篇(入门)
【C++打怪之路Lv1】-- C++开篇(入门)
179 0
|
分布式计算 Java 编译器
【C++入门(下)】—— 我与C++的不解之缘(二)
【C++入门(下)】—— 我与C++的不解之缘(二)
|
10月前
|
编译器 C++ 开发者
【C++篇】深度解析类与对象(下)
在上一篇博客中,我们学习了C++的基础类与对象概念,包括类的定义、对象的使用和构造函数的作用。在这一篇,我们将深入探讨C++类的一些重要特性,如构造函数的高级用法、类型转换、static成员、友元、内部类、匿名对象,以及对象拷贝优化等。这些内容可以帮助你更好地理解和应用面向对象编程的核心理念,提升代码的健壮性、灵活性和可维护性。
|
6月前
|
人工智能 机器人 编译器
c++模板初阶----函数模板与类模板
class 类模板名private://类内成员声明class Apublic:A(T val):a(val){}private:T a;return 0;运行结果:注意:类模板中的成员函数若是放在类外定义时,需要加模板参数列表。return 0;
191 0
|
6月前
|
存储 编译器 程序员
c++的类(附含explicit关键字,友元,内部类)
本文介绍了C++中类的核心概念与用法,涵盖封装、继承、多态三大特性。重点讲解了类的定义(`class`与`struct`)、访问限定符(`private`、`public`、`protected`)、类的作用域及成员函数的声明与定义分离。同时深入探讨了类的大小计算、`this`指针、默认成员函数(构造函数、析构函数、拷贝构造、赋值重载)以及运算符重载等内容。 文章还详细分析了`explicit`关键字的作用、静态成员(变量与函数)、友元(友元函数与友元类)的概念及其使用场景,并简要介绍了内部类的特性。
281 0