从C语言到C++①(第一章_C++入门_上篇)C++学习介绍(命名空间和C++输入输出流)(下)

简介: 从C语言到C++①(第一章_C++入门_上篇)C++学习介绍(命名空间和C++输入输出流)

从C语言到C++①(第一章_C++入门_上篇)C++学习介绍(命名空间和C++输入输出流)(上):https://developer.aliyun.com/article/1513630

6.2命名空间里的内容

命名空间里的内容,不仅仅可以存放变量,

还可以在里面放函数,结构体,甚至是 类(我们后面会讲)。

还可以在命名空间里放命名空间,(命名空间的嵌套,就是需要用多层:: 没什么用)

#include <stdio.h>
namespace N1 
{
  int a = 10;
  int b = 20;
  int Add(int x, int y) 
  {
    return x + y;
  }
}
namespace N2 
{
  int c = 0;
  struct Node 
  {
    struct Node* next;
    int val;
  };
}
int main()
{
  int res = N1::Add(N1::a, N1::b);
  printf("result = %d", res);
 
  struct N2::Node node1;
 
  return 0;
}

6.3命名空间重名问题

命名空间是用来解决命名冲突问题的,

那我项目中定义的某个命名空间的名字和其他命名空间的名字冲突了怎么办?

其实, 在同一个工程中是允许存在多个相同名称的命名空间的。

编译器最后会将他们合成到同一个命名空间中的。

有两个相同名字的命名空间,就会合二为一。有三个相同名字的命名空间,就会三合一……

所以:同一个工程中允许存在多个相同的命名空间,编译器最后会将它们合成到一起。

6.4命名空间展开问题

假设有这样的一种情况,一个命名空间中的某个成员是我们经常要使用的:

#include <stdio.h>
namespace N1 
{
  int a = 10;  // 假设a经常需要使用
  int b = 20;
  int c = 30;
}
 
void func(int n) 
{
  printf("HI, %d\n", n);
}
 
int main()
{
   printf("%d\n", N1::a);
   int res = N1::a;
   func(N1::a);
   printf("hello, %d\n", N1::a);
 
  return 0;
}

指定的作用域,能够做到最好的命名隔离,但是使用起来好像不是很方便。

每次使用都要调 : :  这也太难受了,有办法能解决吗?

可以用 using namespace 将整个命名空间展开,因为命名空间是在全局土生土长的,所以展开后,里面的东西自然会被展开到全局

using namespace 空间名;
#include <stdio.h>
 
namespace N1 
{
  int a = 10;  // 假设a经常需要使用
  int b = 20;
  int c = 30;
}
 
void func(int n)
{
  printf("HI, %d\n", n);
}
 
using namespace N1;  // 将N1这个命名空间展开
 
int main()
{
   printf("%d\n", a); // 这样我们就可以直接使用了,就不需要 "::" 了
   int res = a;
   func(a);
   printf("hello, %d\n", a);
 
  return 0;
}

6.5匿名命名空间

在C语言学习结构体的时候,就提到过匿名结构体。

命名空间这里也可以匿名。如果一个命名空间没有名称,我们就称它为匿名结构体。

// 匿名命名空间
namespace
{
  char c;
  int i;
  double d;
}

这种情况,编译器会在内部给这个没有名字的 "匿名命名空间" 生成一个惟一的名字。

并且还会为该匿名命名空间生成一条 using 指令,所以上面的代码会等同于:

namespace _UNIQUE_NAME 
{
  char c;
  int i;
  double d;
}
using namespace _UNIQUE_NAME;

这里只需要知道有这么一个东西就可以了。


7.C++的输入与输出

刚才之所以讲解命名空间,就是为了让大家能够慢慢地看懂前面写的 Hello World!

#include <iostream>
using namespace std;
 
int main()
{
  cout << "Hello World!" << endl;
 
  return 0;
}

但是在讲解C++的输入与输出之前,还需要再对命名空间做一个小小的补充。


库也是会用命名空间的,C++库的实现定义包含在了一个叫 std 的命名空间中。


加上 using namespace std ; 是为了把 std 空间中所有的内容都展开,


这样就可以直接使用它们了,前面说过这样实际是不好的,但平时练习时可以这样写。


为什么C++要把它封装到一个叫 std 的命名空间中呢?


因为这样就不容易冲突了,有效放置了冲突命名。


注意事项:这里要提一下,有些老的教材上有  #include <iostream.h>


这个在老的编译器上是可以的,比如 VC6.0 ,比较老的版本的库,没有命名空间。


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

7.1 输入和输出

cout 标准输出(控制台)和 cin 标准输入(键盘)时,必须包含 <iostream> 头文件。

并且需要使用 std 标准命名空间,这里会详细探讨。

7.1.1 流插入运算符 <<

cout 后面的 << ,我们称之为 "流插入运算符" 。就像水流的流向一样。

cout 用法演示:

#include <iostream>
using namespace std;
 
int main()
{
  cout << "Hello";  // 等同于 printf("Hello");
 
  return 0;
}

上面的代码,之所以可以直接用 cout,是因为我们已经把 std 这块库命名空间展开了。


下面会对专门对展开方式进行一个探讨。


此外,如果想换行,可以使用 endl 。它就"相当于" \n,都可以起到一个换行的效果。


大量输入输出时尽量少用或者不用 endl ,每次 endl 会刷新缓冲区,这增加了 io 次数,


在数据非常大的时候尽量不要用endl,转义字符不存在刷新缓冲区的问题。


即 —— 需要大量输入输出时建议用 \n 替换 endl 。


使用 C++ 的输入输出是很方便的,它最大的特点就是可以自动识别类型。

#include <iostream>
using namespace std;
 
int main()
{
  int i = 10;
  double d = 3.14;
  
  cout << i << " " << d << endl;   // 相当于 printf("%d %f\n", i, d);
 
  return 0;
}

这就比C语言方便多了。


7.1.2 流提取运算符 >>

cin 后面的 >> ,称之为 "流提取运算符" 。和C语言scanf作用一样,但和上面流插入 << 一样,也是会自动识别类型。

#include <iostream>
using namespace std;
 
int main()
{
  int i = 0;
  double d = 0.0;
 
  cout << "请输入一个整数和一个小数: ";
  cin >> i >> d;
 
  cout << "你输入的是: ";
  cout << i << " 和 " << d << endl;
 
  return 0;
}


7.2 C和C++的混合使用

前面说过C++是兼容C的,因为 <iostream> 有些平台间接的包了 printf 等 C语言中的函数。

有人这时候就会觉得,C++的输入和输出可以自动识别类型,这也太爽了吧,既然 C++ 的输入输出这么好用,那我们是不是就用不上 C语言里的输入输出了?


不是,举个简单的栗子:


如果我们想打印某个浮点数,如何控制小数点后的位数呢?在 C++ 的输入中,这是一件比较麻烦的事情。如果想控制小数点的位数,我们完全可以使用C语言的输入:printf("%.2f", d);


因此,并不是说学了C++的输入输出,就不用C语言的输入输出了。


C++ 和 C语言的输入输出可以混在一起写,混在一起用。


什么时候用 C++ 的,什么时候用 C语言的,看情况就可以了。


(在后面熟悉C++后还能用C++和C一起打面向过程和面向对象的组合拳)

struct Student
{
    char name[20];
    int age;
};
 
int main()
{
    // 这种情况C++ 就不方便了
    struct Student s = {"xiaoming", 18};
    cout << "姓名:" << s.name << endl;    
    cout << "年龄:" << s.age << endl << endl;
 
    // 用c呢?
    printf("姓名:%s\n 年龄:%d\n", s.name, s.age);  
    // 所以说C语言也是有它的优势的
 
    return 0;
}

7.3 再看命名空间的展开

上面我们讨论过使用 using namespace 展开的缺陷,会失去隔离的效果。

这样写好吗?不好。这么一来就全展开来了,所以可以这么写:

采用方式一:空间名 + 作用域限定符

#include <iostream>
//using namespace std;
 
int main() 
{
    // cout << "hello world!\n" << endl; 
    std::cout << "hello world!" << std::endl;  // 指定命名空间
 
    return 0;
}

采用方式二:使用 using namespace 命名空间名称引入 (会破坏隔离效果)

#include <iostream>
using namespace std;
 
int main()
{
  cout << "hello world!" << endl;
 
  return 0;
}

虽然 using namespace 会破坏隔离效果,但是我们平时写练习还是可以这么去做的。因为我们平时不需要这么过分地讲究命名空间,但是以后在写项目或干正事的时候就得讲究讲究了。

采用方式三:使用 using 将命名空间中成员引入

#include <iostream>
 
using std::cout; // 把常用的展开
using std::endl;
 
int main()
{
    cout << "hello world!" << endl;  
 
    return 0;
}

8.再看Hello World!

#include <iostream>
using namespace std;
 
int main()
{
  cout << "Hello World!" << endl;
 
  return 0;
}

现在是不是都能明白了?恭喜你学会Hello World!了,正式踏上了C++的学习之路!

学习C++是一个漫长的过程,当然你可以逝逝下面的21天学会C++:

本篇完。

目录
相关文章
|
8天前
|
存储 安全 编译器
c++入门
c++作为面向对象的语言与c的简单区别:c语言作为面向过程的语言还是跟c++有很大的区别的,比如说一个简单的五子棋的实现对于c语言面向过程的设计思路是首先分析解决这个问题的步骤:(1)开始游戏(2)黑子先走(3)绘制画面(4)判断输赢(5)轮到白子(6)绘制画面(7)判断输赢(8)返回步骤(2) (9)输出最后结果。但对于c++就不一样了,在下五子棋的例子中,用面向对象的方法来解决的话,首先将整个五子棋游戏分为三个对象:(1)黑白双方,这两方的行为是一样的。(2)棋盘系统,负责绘制画面。
|
3月前
|
存储 分布式计算 编译器
C++入门基础2
本内容主要讲解C++中的引用、inline函数和nullptr。引用是变量的别名,与原变量共享内存,定义时需初始化且不可更改指向对象,适用于传参和返回值以提高效率;const引用可增强代码灵活性。Inline函数通过展开提高效率,但是否展开由编译器决定,不建议分离声明与定义。Nullptr用于指针赋空,取代C语言中的NULL。最后鼓励持续学习,精进技能,提升竞争力。
|
4月前
|
存储 缓存 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 的奥秘,从入门到高效编程
|
5月前
|
C++ 开发者
C++学习之继承
通过继承,C++可以实现代码重用、扩展类的功能并支持多态性。理解继承的类型、重写与重载、多重继承及其相关问题,对于掌握C++面向对象编程至关重要。希望本文能为您的C++学习和开发提供实用的指导。
94 16
|
6月前
|
算法 网络安全 区块链
2023/11/10学习记录-C/C++对称分组加密DES
本文介绍了对称分组加密的常见算法(如DES、3DES、AES和国密SM4)及其应用场景,包括文件和视频加密、比特币私钥加密、消息和配置项加密及SSL通信加密。文章还详细展示了如何使用异或实现一个简易的对称加密算法,并通过示例代码演示了DES算法在ECB和CBC模式下的加密和解密过程,以及如何封装DES实现CBC和ECB的PKCS7Padding分块填充。
141 4
2023/11/10学习记录-C/C++对称分组加密DES
|
8月前
|
编译器 C语言 C++
配置C++的学习环境
【10月更文挑战第18天】如果想要学习C++语言,那就需要配置必要的环境和相关的软件,才可以帮助自己更好的掌握语法知识。 一、本地环境设置 如果您想要设置 C++ 语言环境,您需要确保电脑上有以下两款可用的软件,文本编辑器和 C++ 编译器。 二、文本编辑器 通过编辑器创建的文件通常称为源文件,源文件包含程序源代码。 C++ 程序的源文件通常使用扩展名 .cpp、.cp 或 .c。 在开始编程之前,请确保您有一个文本编辑器,且有足够的经验来编写一个计算机程序,然后把它保存在一个文件中,编译并执行它。 Visual Studio Code:虽然它是一个通用的文本编辑器,但它有很多插
196 6
|
4月前
|
编译器 C++ 开发者
【C++篇】深度解析类与对象(下)
在上一篇博客中,我们学习了C++的基础类与对象概念,包括类的定义、对象的使用和构造函数的作用。在这一篇,我们将深入探讨C++类的一些重要特性,如构造函数的高级用法、类型转换、static成员、友元、内部类、匿名对象,以及对象拷贝优化等。这些内容可以帮助你更好地理解和应用面向对象编程的核心理念,提升代码的健壮性、灵活性和可维护性。
|
8天前
|
人工智能 机器人 编译器
c++模板初阶----函数模板与类模板
class 类模板名private://类内成员声明class Apublic:A(T val):a(val){}private:T a;return 0;运行结果:注意:类模板中的成员函数若是放在类外定义时,需要加模板参数列表。return 0;
|
8天前
|
存储 编译器 程序员
c++的类(附含explicit关键字,友元,内部类)
本文介绍了C++中类的核心概念与用法,涵盖封装、继承、多态三大特性。重点讲解了类的定义(`class`与`struct`)、访问限定符(`private`、`public`、`protected`)、类的作用域及成员函数的声明与定义分离。同时深入探讨了类的大小计算、`this`指针、默认成员函数(构造函数、析构函数、拷贝构造、赋值重载)以及运算符重载等内容。 文章还详细分析了`explicit`关键字的作用、静态成员(变量与函数)、友元(友元函数与友元类)的概念及其使用场景,并简要介绍了内部类的特性。