【C++杂货铺】C++介绍、命名空间、输入输出

简介: 【C++杂货铺】C++介绍、命名空间、输入输出

0c6d449e585043fc93273b9f0e605e93.gif

一、C++前言介绍

1.1 什么是C++?


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

1.2 C++的发展史

1979年,贝尔实验室的本贾尼等人试图分析unix内核的时候,试图将内核模块化,于是在C语言的基础上进行扩展,增加了类的机制,完成了一个可以运行的预处理程序,称之为C with classes。

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


2016ccc400e14c4b8e60e59224aaef31.png

 C++还在不断的向后发展。但是:现在社会上主流使用还是C++98和C++11,所有重点要把C++98和C++11掌握好,随着对C++理解不断加深,有时间可以去琢磨下更新的特性。

二、C++关键字

 C++一共有63个关键字,如下所示:


ae5f4c658eaf4346aa44f6dfa25464fc.png

三、命名空间

3.1 为什么要有命名空间?

大型程序一般会使用多个独立开发的库,这些库又可能定义大量的全局变量的名字,如类、函数和模板等。当程序用到多个供应商提供的库时,不可避免地会发生某些名字相互冲突地情况。多个库将名字放置在全局命名空间中将引发命名空间污染(namespace pollution)。

 为了解决上面的问题,于是提出了命名空间的概念,命名空间分割了全局命名空间,其中每一个命名空间是一个作用域。域是一种空间概念,常见的域有:局部域、全局域、类域、命名空间域,域会影响访问和生命周期。

3.2 命名空间定义

 一个命名空间的定义包含两部分:首先是关键字namespace,随后是命名空间的名字。在命名空间名字后面是一系列由花括号括起来的声明和定义。只要是能出现在全局作用域中的声明就能置于命名空间内,主要包括:类、变量(及其初始化操作)、函数(及其定义)、模板和其他命名空间(这意味着命名空间可以嵌套):

namespace wcy//命名空间的名字
{
  //定义变量
  int rand = 10;
  //定义函数
  int Add(int left, int right)
  {
    return left + right;
  }
  //定义类型
  struct Node
  {
    struct Node* next;
    int val;
  };
  //嵌套命名空间
  namespace N2
  {
    int c;
    int d;
    int Sub(int left, int right)
    {
      return left - right;
    }
  }
}

上面的代码定义了一个名为wcy的命名空间,该命名空间包含有变量、函数、类型、命名空间。和其他名字一样,命名空间的名字也必须在定义它的作用域内保持唯一,如果在同一个作用域中出现多个相同名字的命名空间,编译器最后会把他们合并,这意味着命名空间可以是不连续的。命名空间既可以定义在全局作用域内,也可以定义在其他命名空间中,但是不能定义在函数或类的内部。

小tips:

 命名空间作用域后面无须跟分号。

3.3 每一个命名空间都是一个作用域

和其他作用域类似,命名空间中的每个名字都必须表示该命名空间内的唯一实体。因为不同命名空间的作用域不同,所以在不同命名空间内可以有相同名字的成员。

 定义在某个命名空间中的名字可以被该命名空间内的其他成员直接访问,也可以被这些成员内嵌作用域中的任何单位访问。位于该命名空间之外的代码则必须通过域作用限定符::明确指出所用的名字属于哪个命名空间。

namespace wcy
{
  int a = 10;
}
int a = 30;
int main()
{
  int a = 20;
  printf("%d\n", a);
  printf("%d\n", ::a);
  printf("%d\n", wcy::a);
  return 0;
}

eace1e21fb3a4c0d91f2f430b14724c9.png

 上面的代码在局部域、全局域、wcy命名空间域中分别定义了一个a变量并且赋了不同的值,在没指定作用域的时候,会根据局部优先的原则去访问局部变量;::a的左边什么也没有意味着去全局域中查找;wcy::a则指定了要到wcy这个域里面去查找。

3.4 命名空间的使用方法

命名空间有以下三种使用方法:

  • 加命名空间名称以及作用域限定符
int main()
{
    printf("%d\n", wcy::a);
    return 0;    
}

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

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

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

 可以用using namespace wcy将命名空间展开,把命名空间中的成员提升到包含命名空间本身和using指示最近的作用域。

namespace wcy
{
  int a = 10;
  int b = 5;
  int c = 100;
}
int a = 30;
using namespace wcy;
int main()
{
  printf("%d\n", a);//a不明确,出现二义性
  printf("%d\n", ::a);//正确:访问全局的a
  printf("%d\n", wcy::a);//正确:访问wcy中的a
  printf("%d\n", b);//正确,去访问wcy中的b
  int c = 89;//当前局部变量的c隐藏了wcy::c
  c++;//当前局部的c设置成90
  return 0;
}

以上面的代码为例,通过using把wcy命名空间展开,这个过程相当于把wcy中的名字“添加”到全局作用域中,这使得程序可以直接访问wcy中的所有名字。

 当命名空间被注入到它的外层作用域之后,很可能该命名空间中定义的名字会与其外层作用域中的成员冲突。例如在主函数中,wcy的成员a就与全局作用域中的a产生了冲突。这种冲突是允许存在的,但是要想使用冲突的名字,我们就必须明确指出名字的版本。main函数中所有未加限定的a都会产生二义性错误。

 为了使用像a这样的名字,我们必须使用作用域运算符来明确指出所需的版本。我们使用::a来表示全局作用域中的a,而使用wcy::a来表示定义在wcy中的a。

 因为main的作用域和命名空间的作用域不同,所以main内部的声明可以隐藏命名空间中的某些成员的名字。例如,局部变量c隐藏了命名空间的成员wcy::c。在main中使用c不存在二义性,他指的就是局部变量c。

3.5 嵌套的命名空间

 嵌套的命名空间同时是一个嵌套的作用域,它嵌套在外层命名空间的作用域中。嵌套的命名空间中的名字遵循的规则与往常类似:内层命名空间声明的名字将隐藏外层命名空间声明的 同名成员。在嵌套的命名空间中定义的名字只在内层命名空间中有效,外层命名空间的代码想要访问它必须在名字前添加限定符。

namespace wcy
{
  int a = 10;
  namespace wcy1
  {
    int a = 900;//将外层作用域的a隐藏了
    int d = 1000;
  }
  //int b = d;//不正确:d是未声明的标识符
  int b = wcy1::d;//正确访问的是wcy1里面的d
  namespace wcy2
  {
    int f = wcy1::d;//正确
  }
}
int main()
{
  printf("%d\n", wcy::wcy2::f);
  printf("%d\n", wcy::wcy1::a);
  printf("%d\n", wcy::a);
  return 0;
}

3.6 C++标准库的命名空间

 std是C++标准库的命名空间,C++将标准库的定义实现都放到这个命名空间中。

std命名空间的使用惯例:

  • 在日常练习中,建议直接用using namespace std即可,这样很方便。
  • 在项目开发中由于代码较多、规模大,就很容易出现冲突问题,所以建议指定命名空间去访问或者使用using把常用的名字引入。

四、C++输入和输出

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

代码说明:

使用cout标准输出对象(控制台)和cin标准输入对象(键盘)时,必须包含头文件以及按命名空间使用方法使用std。

cout和cin是全局的流对象,endl是特殊的C++符号,表示换行输出,它们都包含在头文件中。

<<是流插入运算符,>>是流提取运算符。

使用C++的输入输出更加方便,不需要像printf和scanf输入输出那样,需要手动控制格式。C++的输入输出可以自动识别变量类型(本质上是运算符重载),但cout和cin的效率比较低。

实际上cout和cin分别是ostream和istream类型的对象,>>和<<也涉及运算符重载等知识,这些我将在后面逐一分享给大家。

注意:

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

 今天的分享到这里就结束啦!如果觉得文章还不错的话,可以三连支持一下,您的支持就是春人前进的动力!


目录
相关文章
|
2月前
|
程序员 C++ 开发者
C++命名空间揭秘:一招解决全局冲突,让你的代码模块化战斗值飙升!
【8月更文挑战第22天】在C++中,命名空间是解决命名冲突的关键机制,它帮助开发者组织代码并提升可维护性。本文通过一个图形库开发案例,展示了如何利用命名空间避免圆形和矩形类间的命名冲突。通过定义和实现这些类,并在主函数中使用命名空间创建对象及调用方法,我们不仅解决了冲突问题,还提高了代码的模块化程度和组织结构。这为实际项目开发提供了宝贵的参考经验。
47 2
|
21天前
|
程序员 C++ 容器
C++编程基础:命名空间、输入输出与默认参数
命名空间、输入输出和函数默认参数是C++编程中的基础概念。合理地使用这些特性能够使代码更加清晰、模块化和易于管理。理解并掌握这些基础知识,对于每一个C++程序员来说都是非常重要的。通过上述介绍和示例,希望能够帮助你更好地理解和运用这些C++的基础特性。
32 0
|
1月前
|
C语言 C++
C++(六)Namespace 命名空间
命名空间(Namespace)是为了解决大型项目中命名冲突而引入的机制。在多库集成时,不同类库可能包含同名函数或变量,导致冲突。C++通过语法形式定义了全局无名命名空间,并允许对全局函数和变量进行作用域划分。命名空间支持嵌套与合并,便于协同开发。其使用需谨慎处理同名冲突。
|
2月前
|
编译器 C语言 C++
C++入门 | 命名空间、输入输出、缺省参数
C++入门 | 命名空间、输入输出、缺省参数
40 4
|
3月前
|
安全 编译器 C++
C++一分钟之-C++中的属性命名空间
【7月更文挑战第22天】C++11引入属性作为元数据,虽无内置属性命名空间,但可通过自定义属性与命名空间组合实现类似效果。例如,创建`perf`命名空间存放`slow`和`fast`属性来标记函数性能。正确使用属性需注意位置、避免重复和确保与实现一致,以提升代码可读性和编译器理解。通过模拟属性命名空间,可以更有效地管理和使用属性。
41 1
|
3月前
|
小程序 C++
【C++入门 二 】学习使用C++命名空间及其展开
【C++入门 二 】学习使用C++命名空间及其展开
|
3月前
|
C语言 C++ 开发者
C++基础知识(一:命名空间的各种使用方法)
C++在C的基础上引入了更多的元素,例如类,类的私密性要比C中的结构体更加优秀,引用,重载,命名空间,以及STL库,模板编程和更多的函数,在面向对象的编程上更加高效。C语言的优势则是更加底层,编译速度会更快,在编写内核时大多数都是C语言去写。 在C++中,命名空间(Namespace)是一种组织代码的方式,主要用于解决全局变量、函数或类的命名冲突问题。命名空间提供了一种封装机制,允许开发者将相关的类、函数、变量等放在一个逻辑上封闭的区域中,这样相同的名字在不同的命名空间中可以共存,而不会相互干扰。
|
4月前
|
C++
C++命名空间(namespace)的使用
C++命名空间(namespace)的使用
|
4月前
|
Unix 编译器 C语言
【C++航海王:追寻罗杰的编程之路】关键字、命名空间、输入输出、缺省、重载汇总
【C++航海王:追寻罗杰的编程之路】关键字、命名空间、输入输出、缺省、重载汇总
23 0
|
4月前
|
编译器 C语言 C++
【C++】:C++关键字,命名空间,输入&输出,缺省参数
【C++】:C++关键字,命名空间,输入&输出,缺省参数
35 0