C++ 重载 , 缺省参数 , 命名空间

本文介绍了C++相较于C语言的新特性,包括面向对象编程的基本概念如封装、继承和多态,新增的class类型及其使用方式,函数重载的概念及其实现原理,缺省参数的用法,以及命名空间的作用。

C++ 简介

C几乎是C++的一个子集,所以C语言支持的语法在C++基本都支持并需要使用。既然名字叫做 C plus plus(C++), 所以它在C的基础上又有了很多新的特性。
C 语言是面向过程的
而 C++ 是面向对象的
面向对象的三大特性就是

封装
继承
多态

C++ 中比 C 语言多了一个 class 类型
任何事物都可以写成一个类 class

class Student {
public:
    void print() {
        cout << m_name << endl;
        cout << m_name << endl;
    }

private:
    char* m_name;
    size_t m_age;
}

例如上面的这个学生类 , 有姓名 , 年龄 , 两个成员变量 , 还有一个 print 成员函数
其实和 C 语言的结构体很像 , 就是多了一个 成员函数
其中的 publicprivate 叫做访问限定符 , 用来规定访问权限

重载

C 语言中的函数 , 不可以同名 , 但是在 C++ 中是可以存在同名函数的
只要同名的函数满足一下条件即可

在同一作用域类
参数列表不同(个数不同 / 类型不同)
返回值可同可不同 // 为什么 ?

编译过程一般分为:
预处理 — 编译 — 汇编 — 链接

预处理:展开头文件,宏替换,去掉注释,条件编译等工作。生成.i文件
编译:语法检查,生成汇编代码。 生成.s文件
汇编:将汇编代码转成机器码 。 生成.o文件
链接:将之前生成的文件链接到一起,生成可执行文件 , .out文件

如果有多个.cpp文件,在链接之前各文件都是独立向下进行的,各文件之间没有交集。

所以C++支持重载的原因 , 就在链接这个阶段上,C语言在链接的时候根据函数名找要调用的函数
C++而是根据函数名和参数类型来寻找要调用的函数

例如下面的代码 , 我写了两个 print 函数

#include <iostream>
#include <string>
using namespace std;

void print()
{
    cout << "Jim" << endl;
    cout << 21 << endl;
}
void print(string t_name, size_t t_age)
{
    cout << t_name << endl;
    cout << t_age << endl;
}

int main()
{
    print();
    print("tom", 20);
    return 0;
}

编译完成之后 , 我们用命令 objdump -d a.out > log.txt 反汇编并将结果重定向到log.txt文件中
我们发现在汇编代码中 , 两个 print 函数变成了下面的名字

08048960 <_Z5printv>: 
// void print()

080489d0 <_Z5printSsj>: 
// void print(string t_name, size_t t_age)

可以猜想 , _Z5 代表返回值类型 , print 函数名 , v / Ssj 代表参数列表 , 即 返回值类型+函数名+参数列表

所以C++可以根据函数名和参数类型来寻找要调用的函数 , 也就支持了重载

上面说函数重载的条件 , 返回值可同可不同 // 为什么 ?
这是为了在解析操作符或函数调用时,独立于上下文(不依赖于上下文)

float sqrt(float);
double sqrt(double);

void f(double da, float fla)
{
    float fl = sqrt(da); //调用sqrt(double)
    double d = sqrt(da); //调用sqrt(double)

    fl = sqrt(fla); //调用sqrt(float)
    d = sqrt(fla); //调用sqrt(float)
}

如果考虑了返回值的类型 , 那么上面的函数调用过程就不能独立于上下文了

缺省参数

也就是可以在函数的形参列表中赋一个初值

全缺省参数

int Add1 (int a = 0, int b = 0) 
{     
    return a + b; 
}

半缺省参数

int Add2 (int a, int b = 0) 
{     
    return a + b; 
}
void Test ()
{
    Add1(); // 0
    Add1(1); // 1
    Add1(1, 1); // 2
    Add2(2); // 2
    Add2(2, 2); // 4
}

默认参数只能从右往左设置
因为函数调用时是从左往右匹配参数的

int add(int a = 0, int b);

这样就没什么意义了 , 因为调用函数 add() , 总会把默认参数覆盖

命名空间

命名空间域是随标准C++而引入的。
它相当于一个更加灵活的文件域(全局域)
可以用花括号把文件的一部分括起来,并以关键字 namespace 开头给它 起一个名字

namespace name1
{
    int a = 0;
}
namespace name2
{
    int a = 1;
}
name1::a = 3;
name2::a = 4;

命名空间域解决全局命名冲突的问题
标准C++库中的所有组件都是在一个被称为std的命名空间中声明和定义的
在采用标准C++的平台上使用标准C++库中的组件,只要写一个using指示符: using namespace std;
就可以直接使用标准C++库中的所有成员
或者 std::成员 的方式也可以使用C++库里的成员
其中 :: 叫 作用域解析符

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值