C嘎嘎~~【初识C++ 上篇】

简介: 转眼间, 就进入C++这个新的篇章啦!

转眼间, 就进入C++这个新的篇章啦!

我带着些许心悸 和 激动:

心悸的是, 时间过的是如此之快, 上个学期咋们还在一起谈着C语言, 数据结构, 现在又要一起学习C++啦; 心悸的是, 我在上个半年, 耽误了很多时间, 遗漏了许多博客没写。。。

激动的是, 我们终于要爽起来了, 相信我们在学习C++之后, 尤其是学习了C++的STL, 模板之后, 就不想写C语言了(当然, C语言也有自己的优势哎)



C++是在C语言的基础之上, 容纳进去了面向对象编程思想, 并增加了许多有用的库, 以及编程范式等等。


接下来, 我们初识C++(主要是C++98)章节的主要任务是:


了解C语言语法的不足, 以及C++是如何对C语言设计不合理的地方进行优化的

为后续的类和对象学习打基础

🫅1. C++关键字

C++ 总共有63 个 关键字, C语言有32个关键字。 在这个阶段, 我们对关键字只是起着了解作用, 以后碰到会进行详解的。

🫅 2.命名空间

应该不少萌新有些疑问: 啥是命名空间? 命名空间有啥用? 初学者有些疑问是一件好事, 我们可以带着疑问, 去有重点地学习。



让我们先来看看下面的一串代码:


#include<stdio.h>
int size = 4;
int size = 5;
int main()
{
  printf("%d\n", size);
  return 0;
}
*****
error : size 重定义
******

看到上面的代码, 有人就会说: 老陈, 你怎么写出这么挫的代码? 怎么定义了 size 两次?

嘿嘿一笑😀😀, 这么写有它的实际意义啊:你想啊, 你以后参加工作, 肯定是分项目给你和你的同事做啊, 最后把你们的代码合并起来。 如果最后你的代码中的变量名 和 张三的变量名 冲突了?怎么办?打一架、、、😀😀

这时候, 我们的祖师爷 - 本贾尼就想出了一个办法:能不能在每个人的代码之间起一堵 “墙” , 你的变量和函数 在你的区域内部起作用, 出了你的区域就不会起作用了。

这一堵墙的专业名词 就叫做 命名空间


在C/C++中, 变量、函数 和 后面要学的类都是大量存在的, 这些变量、 函数 和 类的名称都存在于全局作用域中, 可能会导致许多冲突。 使用命名空间的目的是 对标识符的名称进行本地化, 以避免命名冲突 或 名字污染, namespace关键字的出现就是针对这种问题的


那么问题来了: 这个namespace 是怎么用的?

🤷‍♂️2.1命名空间的定义

// 1.命名空间内可以定义变量, 函数, 类型
namespace mu
{
  int rand = 5;
  int Sub(int a, int b)
  {
    return a - b;
  }
}
// 2.命名空间可以嵌套
namespace N1
{
  int a;
  int b;
  struct SLTNode
  {
    int val;
    struct SLTNode* next;
  };
  namespace N2
  {
    int a;
    int b;
    struct SLTNode
    {
      int val;
      struct SLTNode* next;
    };
  }
}
// 3.同一个工程中允许多个相同的命名空间, 编译器最终会合并成一个命名空间中
// eg: 如果一个工程中, 存在着 test.cpp , CSDN.cpp 两个文件, 
// 这两个文件都存在着 N1 这个命名空间, 最终会合并成一个N1的命名空间

总结:


1.命名空间的构成: 关键字 namespace, 命名空间名(自己定), {}(注意跟结构体区分开, 后面没有 逗号 ;)

2.一个命名空间就定义了一个新的作用域(但是这个不影响生命周期),命名空间内的内容都局限于改命名空间中

3.命名空间的作用: 解决全局的命名冲突问题

这里有人就会十万个为什么: 为什么不解决局限的命名冲突问题啊?

首先, 我们都知道局部变量是不能重定义的, 它重定义 一是 语法问题, 二是 没啥用。

其次, 我们应该明确,我们现在学的知识是为了后面的类、 对象学习打基础。 这些玩意都是存在于全局作用域中的, 解决的是他们的命名冲突问题


🤷‍♂️2.2命名空间的使用

学到这里, 有些人又有些疑问: 老陈, 我把我写的代码用命名空间包了起来, 那我们在工程中又怎么使用自己写的代码??

好问题! 这就是我们即将要讲的命名空间的使用。

系好安全带, 我们发车了!!🤞🤞


我们先了解一下编译器对域(墙)的搜索顺序:

dce752fe7d8440698318921246071ce0.png

那我们如何突破局部域 和 全局域 , 从而访问到我们的命名空间域呢??

一共有三种方式:


1.用作用域限定符(::)去访问

namespace N
{
  int a = 10;
  int b = 8;
  struct SLTNode
  {
    int val;
    struct SLTNode* next;
  };
}
int main()
{
  printf("%d\n", N::a);
  return 0;
}

2.使用 using 展开某命名空间的成员

namespace N
{
  int a = 10;
  int b = 8;
  struct SLTNode
  {
    int val;
    struct SLTNode* next;
  };
}
using N::b;
int main()
{
  printf("%d\n", b);
  return 0;
}

3.使用using namespace 展开某个命名空间域

namespace N
{
  int a = 10;
  int b = 8;
  struct SLTNode
  {
    int val;
    struct SLTNode* next;
  };
}
using namespace N;
int main()
{
  printf("%d\n", a);
  printf("%d\n", b);
  return 0;
}

总结一下上面的几种情形:

aa4c5c65cd9b4dbc9b84fc07f69bd40e.png


🫅 3.C++输入 & 输出

有些老铁, 到了这里就想问: 老陈, 我们搞了这么多东西, 还不知道 C++ 是如何输入 和 输出的?你这搞得不行啊, 赶快来讲一讲!!


由于C++ 兼容 C语言, 那么scanf 和 printf 还是照常能用的, 不过需要引用 头文件 cstdio , 不过好像在最新的C++语法里, 引用头文件 iostream 就能照用 这两个函数 。


#include<iostream>
// #include<cstdio>
int main()
{
  int a = 0;
  scanf("%d", &a);
  printf("%d\n", a);
  return 0;
}
*****
5
5
*****

有些老铁又要问了: 那C++有么有自己专用的输入 和 输出 函数啊?cin 和 cout 就是你们要的答案

先别发问, 我先给你们看一下例子:


#include<iostream>
using namespace std;
int main()
{
  int n;
  cin >> n;
  cout << n << endl;
  return 0;
}
*****
5
5
*****

说明:

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

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

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

4.使用C++输入输出更方便,不需要像printf/scanf输入输出时那样,需要手动控制格式。C++的输入输出可以自动识别变量类型。

5.实际上cout和cin分别是ostream和istream类型的对象,>>和<<也涉及运算符重载等知识,这些知识我们我们后续才会学习,所以我们这里只是简单学习他们的使用。后面我们还有有一个章节更深入的学习IO流用法及原理。


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


🐉🐉🐉🐉🐉

std是C++标准库的命名空间,如何展开std使用更合理呢?


1.在日常练习中,建议直接using namespace std即可,这样就很方便。

2.using namespace std展开,标准库就全部暴露出来了,如果我们定义跟库重名的类型/对象/函数,就存在冲突问题。该问题在日常练习中很少出现,但是项目开发中代码较多、规模大,就很容易出现。所以建议在项目开发中使用,像std::cout这样使用时指定命名空间 + using std::cout展开常用的库对象/类型等方式。


自是汝才难用世,岂真吾相不当侯?

须知少日拏云志,曾许人间第一流


相关文章
|
编译器 C语言 C++
C嘎嘎~~[谈谈C++的一些优化]
C嘎嘎~~[谈谈C++的一些优化]
|
存储 安全 编译器
C嘎嘎~~ 【初识C++ 下篇】
C嘎嘎~~ 【初识C++ 下篇】
|
存储 编译器 程序员
C嘎嘎~~【初识C++ 中篇】
C嘎嘎~~【初识C++ 中篇】
|
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
|
28天前
|
存储 编译器 Linux
【c++】类和对象(上)(类的定义格式、访问限定符、类域、类的实例化、对象的内存大小、this指针)
本文介绍了C++中的类和对象,包括类的概念、定义格式、访问限定符、类域、对象的创建及内存大小、以及this指针。通过示例代码详细解释了类的定义、成员函数和成员变量的作用,以及如何使用访问限定符控制成员的访问权限。此外,还讨论了对象的内存分配规则和this指针的使用场景,帮助读者深入理解面向对象编程的核心概念。
66 4
|
2月前
|
存储 编译器 对象存储
【C++打怪之路Lv5】-- 类和对象(下)
【C++打怪之路Lv5】-- 类和对象(下)
29 4
|
2月前
|
编译器 C语言 C++
【C++打怪之路Lv4】-- 类和对象(中)
【C++打怪之路Lv4】-- 类和对象(中)
25 4
|
2月前
|
存储 安全 C++
【C++打怪之路Lv8】-- string类
【C++打怪之路Lv8】-- string类
23 1