【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

相关文章
|
2月前
|
编译器 C++
C++入门12——详解多态1
C++入门12——详解多态1
42 2
C++入门12——详解多态1
|
2月前
|
C++
C++入门13——详解多态2
C++入门13——详解多态2
84 1
|
2月前
|
存储 安全 编译器
【C++打怪之路Lv1】-- 入门二级
【C++打怪之路Lv1】-- 入门二级
24 0
|
2月前
|
自然语言处理 编译器 C语言
【C++打怪之路Lv1】-- C++开篇(入门)
【C++打怪之路Lv1】-- C++开篇(入门)
34 0
|
2月前
|
分布式计算 Java 编译器
【C++入门(下)】—— 我与C++的不解之缘(二)
【C++入门(下)】—— 我与C++的不解之缘(二)
|
2月前
|
编译器 Linux C语言
【C++入门(上)】—— 我与C++的不解之缘(一)
【C++入门(上)】—— 我与C++的不解之缘(一)
|
2月前
|
编译器 C++
C++入门11——详解C++继承(菱形继承与虚拟继承)-2
C++入门11——详解C++继承(菱形继承与虚拟继承)-2
32 0
|
15天前
|
存储 编译器 C语言
【c++丨STL】string类的使用
本文介绍了C++中`string`类的基本概念及其主要接口。`string`类在C++标准库中扮演着重要角色,它提供了比C语言中字符串处理函数更丰富、安全和便捷的功能。文章详细讲解了`string`类的构造函数、赋值运算符、容量管理接口、元素访问及遍历方法、字符串修改操作、字符串运算接口、常量成员和非成员函数等内容。通过实例演示了如何使用这些接口进行字符串的创建、修改、查找和比较等操作,帮助读者更好地理解和掌握`string`类的应用。
25 2
|
21天前
|
存储 编译器 C++
【c++】类和对象(下)(取地址运算符重载、深究构造函数、类型转换、static修饰成员、友元、内部类、匿名对象)
本文介绍了C++中类和对象的高级特性,包括取地址运算符重载、构造函数的初始化列表、类型转换、static修饰成员、友元、内部类及匿名对象等内容。文章详细解释了每个概念的使用方法和注意事项,帮助读者深入了解C++面向对象编程的核心机制。
54 5
|
27天前
|
存储 编译器 C++
【c++】类和对象(中)(构造函数、析构函数、拷贝构造、赋值重载)
本文深入探讨了C++类的默认成员函数,包括构造函数、析构函数、拷贝构造函数和赋值重载。构造函数用于对象的初始化,析构函数用于对象销毁时的资源清理,拷贝构造函数用于对象的拷贝,赋值重载用于已存在对象的赋值。文章详细介绍了每个函数的特点、使用方法及注意事项,并提供了代码示例。这些默认成员函数确保了资源的正确管理和对象状态的维护。
56 4