从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++:

本篇完。

目录
相关文章
|
4月前
|
安全 C语言 C++
比较C++的内存分配与管理方式new/delete与C语言中的malloc/realloc/calloc/free。
在实用性方面,C++的内存管理方式提供了面向对象的特性,它是处理构造和析构、需要类型安全和异常处理的首选方案。而C语言的内存管理函数适用于简单的内存分配,例如分配原始内存块或复杂性较低的数据结构,没有构造和析构的要求。当从C迁移到C++,或在C++中使用C代码时,了解两种内存管理方式的差异非常重要。
179 26
|
5月前
|
存储 安全 编译器
c++入门
c++作为面向对象的语言与c的简单区别:c语言作为面向过程的语言还是跟c++有很大的区别的,比如说一个简单的五子棋的实现对于c语言面向过程的设计思路是首先分析解决这个问题的步骤:(1)开始游戏(2)黑子先走(3)绘制画面(4)判断输赢(5)轮到白子(6)绘制画面(7)判断输赢(8)返回步骤(2) (9)输出最后结果。但对于c++就不一样了,在下五子棋的例子中,用面向对象的方法来解决的话,首先将整个五子棋游戏分为三个对象:(1)黑白双方,这两方的行为是一样的。(2)棋盘系统,负责绘制画面。
80 0
|
9月前
|
存储 缓存 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 的奥秘,从入门到高效编程
|
8月前
|
存储 分布式计算 编译器
C++入门基础2
本内容主要讲解C++中的引用、inline函数和nullptr。引用是变量的别名,与原变量共享内存,定义时需初始化且不可更改指向对象,适用于传参和返回值以提高效率;const引用可增强代码灵活性。Inline函数通过展开提高效率,但是否展开由编译器决定,不建议分离声明与定义。Nullptr用于指针赋空,取代C语言中的NULL。最后鼓励持续学习,精进技能,提升竞争力。
|
11月前
|
存储 NoSQL 编译器
【C语言】指针的神秘探险:从入门到精通的奇幻之旅 !
指针是一个变量,它存储另一个变量的内存地址。换句话说,指针“指向”存储在内存中的某个数据。
357 7
【C语言】指针的神秘探险:从入门到精通的奇幻之旅 !
|
10月前
|
存储 编译器 C语言
【C语言程序设计——入门】C语言入门与基础语法(头歌实践教学平台习题)【合集】
本文档介绍了C语言环境配置和编程任务,主要内容包括: - **C语言环境配置**:详细讲解了在Windows系统上配置C语言开发环境的步骤。 - **第1关:程序改错**:包含任务描述、相关知识(如头文件引用、基本语法规则)、编程要求、测试说明及通关代码。 - **第2关:scanf函数**:涉及`scanf`和`printf`函数的格式与使用方法,提供编程要求、测试说明及通关代码。 文档结构清晰,涵盖从环境搭建到具体编程任务的完整流程,适合初学者学习和实践。
282 4
|
10月前
|
C语言
【C语言程序设计——入门】基本数据类型与表达式(头歌实践教学平台习题)【合集】
这份文档详细介绍了编程任务的多个关卡,涵盖C语言的基础知识和应用。主要内容包括: 1. **目录**:列出所有关卡,如`print函数操作`、`转义字符使用`、`数的向上取整`等。 2. **各关卡的任务描述**:明确每关的具体编程任务,例如使用`printf`函数输出特定字符串、实现向上取整功能等。 3. **相关知识**:提供完成任务所需的背景知识,如格式化输出、算术运算符、关系运算符等。 4. **编程要求**:给出具体的代码编写提示。 5. **测试说明**:包含预期输入输出,帮助验证程序正确性。 6. 文档通过逐步引导学习者掌握C语言的基本语法和常用函数,适合初学者练习编程技能。
269 1
|
11月前
|
算法 编译器 C语言
【C语言】C++ 和 C 的优缺点是什么?
C 和 C++ 是两种强大的编程语言,各有其优缺点。C 语言以其高效性、底层控制和简洁性广泛应用于系统编程和嵌入式系统。C++ 在 C 语言的基础上引入了面向对象编程、模板编程和丰富的标准库,使其适合开发大型、复杂的软件系统。 在选择使用 C 还是 C++ 时,开发者需要根据项目的需求、语言的特性以及团队的技术栈来做出决策。无论是 C 语言还是 C++,了解其优缺点和适用场景能够帮助开发者在实际开发中做出更明智的选择,从而更好地应对挑战,实现项目目标。
414 0
|
存储 安全 编译器
【C++打怪之路Lv1】-- 入门二级
【C++打怪之路Lv1】-- 入门二级
121 0