C++:命名空间、缺省函数以及函数的重载


一、命名空间

1.为什么要有命名空间?

在大型程序中,往往会使用到多个独立开发的库,这些库往往会定义大量的全局名字,如类、函数和模版等。当应用程序用到多个库时,不可避免的发生某些名字相互冲突的情况。多个库名字放置在全局变量中将引发命名空间污染。
命名空间(namespace)为防止名字冲突提供了一个更加可控的机制。命名空间分割了全局命名空间,其中每一个命名空间都将是一个作用域。

2.命名空间的定义方法

一个命名空间包含两个部分:首先是关键字namespace,随后是命名空间的名字。在命名空间名字后面是一系列由花括号括起来的声明和定义。
下面简单介绍命名空间的定义方法:

//普通的命名空间
namespace N1
{
    
    
    int a;
    int Fun(int a,int b)
    {
    
    
        return a + b;
    }
}

Note:命名空间作用域后面无须加分号。

//命名空间可以嵌套
namespace N2
{
    
    
    int a;
    int Fun(int a,int b = 0)
    {
    
    
        return a + b;
    }
    namespace N3
    {
    
    
        int b;
        int Fun(double a,int b)
        {
    
    
            return a + b;
        }
    }
}
//在同一个工程中允许存在多个相同的命名空间,编译器最后会合成同一个命名空间中
namespace N1{
    
    
    int Fun(int a,int b)
    {
    
    
        return a + b;
    }
}

namespace N2{
    
    
    int Fun(int a = 1,int b = 2)
    {
    
    
        return a + b;
    }
}

namespace N1{
    
    
    int Fun(double a, double b)
    {
    
    
        return a - b;
    }
}

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

3.命名空间的使用

//加命名空间名称及作用域限定符
namespace N1
{
    
    
    int a = 10,b = 20;
    int Add(int left,int right)
    {
    
    
        return left + right;
    }
    int Sub(int left,int right)
    {
    
    
        return left - right;
    }
}
int main()
{
    
    
    printf("%d\n",N1 :: a);
    return 0;
}
//使用using将命名空间中的成员引入
namespace N1
{
    
    
    int a = 10,b = 20;
    int Add(int left,int right)
    {
    
    
        return left + right;
    }
    int Sub(int left,int right)
    {
    
    
        return left - right;
    }
}
using N1 :: b;
int main()
{
    
    
    printf("%d\n",N1 :: a);
    printf("%d\n",b);
    return 0;
}
//使用using namespace 命名空间名称引入
namespace N1
{
    
    
    int a = 10,b = 20;
    int Add(int left,int right)
    {
    
    
        return left + right;
    }
    int Sub(int left,int right)
    {
    
    
        return left - right;
    }
}
using namespace N1;
int main()
{
    
    
    printf("%d\n",N1 :: a);
    printf("%d\n",b);
    printf("%d\n",Add(10,20));
    return 0;
}

二、缺省参数

1.缺省参数是什么?

缺省参数是在声明或者定义函数时为函数的参数指定一个默认值,在调用该函数时,如果没有制定的实参则采用默认值,否则使用制定的实参

2.缺省参数的分类

using namespace std;
//全缺省参数
void Fun1(int a,int b)
{
    
    
    std::cout << "a = " << a << endl;
    std::cout << "b = " << b << endl;
}

//半缺省参数
void Fun2 (int a,int b = 20)
{
    
    
    std::cout << " a = " << a << endl;
    std::cout << " b = " << b << endl;
}

Note:1.半缺省参数必须从右往左一次给出,不可随意赋值。
2.缺省参数不可以在函数声明和定义中同时出现。
3.缺省值必须是常量。
4.C语言不支持缺省参数(编译器不支持)。

三、函数重载

1.函数重载是什么?

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

using namespace std;
int Add(int a,int b)
{
    
    
    return a + b;
}

double Add(double a, double b)
{
    
    
    return a + b;
}

float Add(float a, float b)
{
    
    
    return a + b;
}

int main()
{
    
    
    Add(10,20);
    Add(10.0,20.0);
    Add(0.1f,0.3f);
    return 0;
}

2.为什么C++支持函数重载,而C语言不支持重载?

在C/C++中,一个程序运行起来需要经过四个阶段:预处理,编译,汇编、链接。下面是我在linux下编译C与C++2个程序的结果:
C++:
在这里插入图片描述

着
由以上两张图可以看出,分别采用g++编译完成后,函数名字的修饰发生了改变,编译器将函数参数类型信息添加到修改后的名字中。

C语言
在这里插入图片描述

在这里插入图片描述
在linux下,采用gcc编译完成后,函数名字的修饰没有发生改变。

综上,C++在编译过程中可以看出,函数命名3取决于函数的参数(包括参数个数或者类型或者顺序),而C语言在编译过程中将一视同仁。

为什么类型相同返回值不同时,函数不能重载?

做一个假设:函数重载与返回值类型,形参类型有关
举个例子:
在这里插入图片描述

我们可以观察出 int Add 在编译阶段被改写成为 _Z3Addii,而double Add 被改写为**_Z3Addii**,所以猜想I ->int d ->double,Z后面的数字3代表了返回类型(这个应该与编译器有关)

所以之所以不考虑函数的返回类型,是因为保持解析操作符或函数调用时候,独立于上下语句,如果返回值类型考虑到函数重载中,这样编译器就无法判断调用哪个函数。

面试题

有几个简单的面试题,列举出来:
1.C语言中为什么不能支持函数重载?
2.C++中重载底层是怎么处理的?
3.C++中能否将一个函数按照C语言的风格来写?

猜你喜欢

转载自blog.csdn.net/xhuyang111/article/details/114362768