C++基础入门——语法详解篇(上)

简介: 本篇文章是对C++的初学者语法进行了详解。也可以理解为从C语言转换到C++的使用必须要学的基础语法的转换。有很多人有所疑问:什么是C++呢?为什么要学C++呢?我们接下来会给出解答的。

本篇文章是对C++的初学者语法进行了详解。也可以理解为从C语言转换到C++的使用必须要学的基础语法的转换。有很多人有所疑问:什么是C++呢?为什么要学C++呢?我们接下来会给出解答的。



一、什么是 C++ 呢?



C语言是结构化和模块化的语言,适合处理较小规模的程序。对于复杂的问题,规模较大的程序,需要高度的抽象和建模时,C语言则不合适。为了解决软件危机, 20世纪80年代, 计算机界提出了OOP(object oriented programming:面向对象)思想,支持面向对象的程序设计语言应运而生。

 1982年,Bjarne Stroustrup博士在C语言的基础上引入并扩充了面向对象的概念,发明了一种新的程序语言。为了表达该语言与C语言的渊源关系,命名为C++。因此:C++是基于C语言而产生的,它既可以进行C语言的过程化程序设计,又可以进行以抽象数据类型为特点的基于对象的程序设计,还可以进行面向对象的程序设计。


二、为什么要学 C++ 呢?


 这里给大家简单总结一下为什么要学C++,也就是C++的重要性:


首先,C++基于C语言扩充了一些语法,引入并扩充了面向对象的概念,支持面向对象。同时C++兼容C语言;

语言使用的广泛度较高;

在工作领域应用范围较广;

校招的重视度较高。

 以上是较为重要的原因。我们也应该认识到C++的重要性。接下来我们直接进入如法的讲解。


三、C++ 基础语法

3、1 C++ 关键字

 C++总计63个关键字,C语言32个关键字。这里我们发改了解一下都有哪些关键字,不在进行详细讲解。


291281a6b6d94a9eab987b62517c26a5.png



3、2 命名空间

3、2、1 为什么要引入命名空间


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


3、2、2 命名空间的定义

定义命名空间,需要使用到namespace关键字,后面跟命名空间的名字,然后接一对{}即可,{}中即为命名 空间的成员。


 代码如下:

namespace namespace_name
{
    //空间成员
    ......
}

 其中在命名空间中可以声明变量、函数、类型等。代码如下:

namespace bit
{
    int rand = 10;
    int Add(int left, int right)
    {
        return left + right;
    }
    struct Node
    {
        struct Node* next;
        int val;
    };
}


命名空间也可以嵌套命名空间,代码如下:

namespace N1
{
    int a;
    int b;
    int Add(int left, int right)
    {
        return left + right;
    }
    namespace N2
    {
        int c;
        int d;
        int Sub(int left, int right)
        {
            return left - right;
        }
    }
}



 同一个工程中允许存在多个相同名称的命名空间,编译器最后会合成同一个命名空间中。例如,上述的嵌套的命名空间中,我们声明了N1的命名空间。当我们再次独立声明一个命名空间N1时,编译器自动会将这两个同名的命名空间N1合并为一个。


 注意:一个命名空间就定义了一个新的作用域,命名空间中的所有内容都局限于该命名空间中。


3、2、3 命名空间的使用


 命名空间该如何使用呢?命名空间的使用有三种方式:

  • 加命名空间名称及作用域限定符;
  • 使用 using 将命名空间中的某个成员引入;
  • 使用 using namespace 命名空间名称 将该命名空间的所有成员引入。

 我们具体可看如下例子:

//有一个命名空间N
//加命名空间名称及作用域限定符
int main()
{
 printf("%d\n", N::a);
 return 0; 
}
//使用using将命名空间中某个成员引入
using N::b;
int main()
{
 printf("%d\n", N::a);
 printf("%d\n", b);
 return 0; 
}
//使用 using namespace 命名空间名称 引入
using namespce N;
int main()
{
 printf("%d\n", N::a);
 printf("%d\n", b);
 Add(10, 20);
 return 0; 
}


我们经常可以看到 using namespace std。学完上面的内容后我们知道 std 是一个命名空间的名称。std 是 s tan dard 的缩写,意思是“标准命名空间”。当然我们也可不直接展开整个 std 命名空间,我们也可用 std::变量名称 进行局部展开,用到某个变量或函数。


 std命名空间的使用惯例:


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

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


3、3 C++的输入和输出

 C++的输入和输出相对C语言更新了和更加便捷了。我们先看一个例子:

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


我们看到上面有 cin 、 cout 和 endl 三个”新东西“,这里给大家解释一下:


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

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

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

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

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


3、4 函数重载

3、4、1 函数重载的概念

 函数重载:是函数的一种特殊情况,C++允许在同一作用域中声明几个功能类似的同名函数,这些同名函数的形参列表(参数个数 或 类型 或 类型顺序)不同,常用来处理实现功能类似数据类型不同的问题。注意:形参列表中的类型顺序是指的不同类型的形参顺序不同我们看下面例子:

#include<iostream>
using namespace std;
// 1、参数类型不同
int Add(int left, int right)
{
    cout << "int Add(int left, int right)" << endl;
    return left + right;
}
double Add(double left, double right)
{
    cout << "double Add(double left, double right)" << endl;
    return left + right;
}
// 2、参数个数不同
void f()
{
    cout << "f()" << endl;
}
void f(int a)
{
    cout << "f(int a)" << endl;
}
// 3、参数类型顺序不同
void f(int a, char b)
{
    cout << "f(int a,char b)" << endl;
}
void f(char b, int a)
{
    cout << "f(char b, int a)" << endl;
}
int main()
{
    Add(10, 20);
    Add(10.1, 20.2);
    f();
    f(10);
    f(10, 'a');
    f('a', 10);
    return 0
}


 其运行结果如下图:

3、4、2 C++支持函数重载的原理


 我们知道C语言是不支持函数重载的,那为什么C++支持函数重载呢?其中的细节又是什么呢?接下为大家简述一下其中的细节。


 我们直到,在C/C++中一个程序要运行起来,需要经历预处理、编译、汇编、链接四个阶段。如果一切正常,最终会生成一个可执行程序。每个阶段都做了什么事情呢?




43dbb144741746ab96ac5f6e8825a414.png

这里的关键就是在链接阶段。链接阶段时处理那些事情呢?我们分为一下几点:


实际项目通常是由多个头文件和多个源文件构成,而通过C语言阶段学习的编译链接,我们可以知道,当前a.cpp中调用了b.cpp中定义的Add函数时,编译后链接前,a.o的目标文件中没有Add的函数地址,因为Add是在b.cpp中定义的,所以Add的地址在b.o中。那么怎么办呢?

所以链接阶段就是专门处理这种问题,链接器看到a.o调用Add,但是没有Add的地址,就会到b.o的符号表中找Add的地址,然后链接到一起。

那么链接时,面对Add函数,链接接器会使用哪个名字去找呢?这里每个编译器都有自己的函数名修饰规则。

 重点来了,C++中在链接阶段引入了函数名修饰规则,这样就可以区分相同函数名不同形参的函数了。链接阶段的函数名修饰规则是什么呢?我们接着往下看。


 这里我们需要在Linux环境下看其汇编代码,比较容易观察:




cd09ade3013649c19c1a6719aeaf17ac.png



通过上图,我们可大致发现在linux下通过g++编译后的函数修饰后变成:_Z+函数长度+函数名+类型首字母。


  通过这种函数名修饰规则我们就可以很好的区分相同函数名不同形参的函数了。在链接阶段,也很容易找到各自对应的地址。这就是C++支持函数重载的根本原因。


 由于内容稍多,本篇文章暂时讲解到这里。后续会给大家更新出下篇文章,对基础语法讲解完毕。希望本篇文章会对你有所帮助,感谢观看ovo~



相关文章
|
2月前
|
编译器 C++
C++入门12——详解多态1
C++入门12——详解多态1
47 2
C++入门12——详解多态1
|
2月前
|
编译器 C语言 C++
C++入门3——类与对象2-2(类的6个默认成员函数)
C++入门3——类与对象2-2(类的6个默认成员函数)
39 3
|
2月前
|
存储 编译器 C语言
C++入门2——类与对象1(类的定义和this指针)
C++入门2——类与对象1(类的定义和this指针)
51 2
|
2月前
|
C++
C++入门13——详解多态2
C++入门13——详解多态2
89 1
|
2月前
|
程序员 C语言 C++
C++入门5——C/C++动态内存管理(new与delete)
C++入门5——C/C++动态内存管理(new与delete)
92 1
|
2月前
|
编译器 C语言 C++
C++入门4——类与对象3-1(构造函数的类型转换和友元详解)
C++入门4——类与对象3-1(构造函数的类型转换和友元详解)
30 1
|
2月前
|
存储 编译器 C++
C++入门3——类与对象2-1(类的6个默认成员函数)
C++入门3——类与对象2-1(类的6个默认成员函数)
51 1
|
2月前
|
编译器 C语言 C++
C++入门6——模板(泛型编程、函数模板、类模板)
C++入门6——模板(泛型编程、函数模板、类模板)
70 0
C++入门6——模板(泛型编程、函数模板、类模板)
|
2月前
|
存储 安全 编译器
【C++打怪之路Lv1】-- 入门二级
【C++打怪之路Lv1】-- 入门二级
30 0
|
2月前
|
自然语言处理 编译器 C语言
【C++打怪之路Lv1】-- C++开篇(入门)
【C++打怪之路Lv1】-- C++开篇(入门)
39 0