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

C++介绍

C语言是一种结构化的程序设计语言。

最初是为了开发UNIX操作系统,由丹尼斯里奇和肯汤姆逊在B语言的基础上于贝尔实验室开发出来的。C语言是一种面向过程的语言,适合处理较小规模的程序。对于复杂的,大规模的程序,需要高度的抽象,此时C语言就不再适合。因此,在C语言的基础上又增加了新的特性————类,最初,称其为“带类的C语言”。后来,又再次基础上增添了更多的新特性。所以,将其重新命名为“C++”。C++是兼容C语言的,因此C语言可以说是C++的一个子集。

C++是一种基于面向对象的程序设计语言(不是纯面向对象的语言,因为它兼容C语言)。

面向对象的三大特性:封装,继承,多态。

其中封装主要体现在两方面:
1. 将程序和数据封装在类中。其中对象是类的实例,类是对对象共有属性的抽象。以对象作为程序的基本单元,以提高程序的复用性,灵活性和扩展性。
2. C++中设置访问限定符,可以实现程序代码块内部的高内聚,代码块之间的高耦合。C++中的限定符有三种:public(公有),private(私有),protected(受保护的)。其中:
(1)public成员在类内类外可以直接访问。private成员在类内可以直接访问,但不能在类外直接访问。protected成员可以在类内部和子类的内部直接访问;
(2)在一个类内部,限定符可以使用多次,限定符的作用域为从定义处到下一个限定符定义处或类结束处;
(3)如果类中没有定义限定符,则类成员默认为私有的。在C++中,struct除了用于声明结构体外,还可以声明类,与class不同的是,struct声明的类如果没有访问限定符,则类成员默认为公有的;

C++中的数据类型:

除了包含C语言中的基本数据类型和自定义数据类型外,还新增了bool类型,class(类)类型。

C++的作用域:

除了包含C语言中的局部域和全局域外,还包含命名空间域和类域。

C++支持函数重载

函数重载:是指在同一作用域内,一组函数的函数名相同,函数的参数类型或者参数个数不同,函数返回值任意(可相同可不同)

C++中支持函数重载,C语言中不支持函数重载。

C语言不支持重载:

reload.c
#include<stdio.h>                                                                                                                                                 
int fun(int a,int b)
{
    return a + b;
}
int fun(double a,int b)
{
    return b;
}
int main()
{
    fun(1,2);
    fun(1.0,2);
    return 0;
}

对上述代码进行编译:
这里写图片描述
由上述结果可以看出C语言中不支持函数重载。

C++支持重载:

reload.cpp
#include<iostream>
using namespace std;
int fun(int a,int b)
{
    return a + b;
}
//函数的重载
int fun(double a,int b)
{
    return b;
}
int main()
{
    cout<<fun(1,2)<<endl;
    cout<<fun(1.0,2)<<endl;
    return 0;
}

编译运行上述程序:
这里写图片描述
通过上述结果可以知道C++支持函数重载。

为什么C++支持重载,C语言不支持重载?

在LInux下对上述两个程序生成目标文件(.o文件),通过以下指令查看汇编代码:

C语言:objdump -D reloadc.o
C++:objdump -D reloadcpp.o

C语言:
C++:
通过上述的结果对比,可以看出C语言中通过函数名对函数进行标识,而在C++中不仅通过函数名还有函数参数的个数和类型来对函数进行标识。当C语言中两函数的函数名相同时,即使参数不同也会被认为是重定义。但是,C++中函数名相同,只要参数不同就可以进行区分。

所以说,C++支持函数重载的原因是符号表中存放的函数名+函数个数+函数类型。C语言不支持函数重载的原因是符号表中存放的只有函数名。

C++中函数的缺省参数

缺省参数:在函数的形参列表中对参数赋予默认值的参数。
函数的参数可以分为:
全缺省参数:形参全部设定默认值
半缺省参数:对部分形参设定默认值
无缺省参数:所有形参都不设定默认值

下面通过代码来说明:

#include<iostream>
using namespace std;
//无缺省
int fun(int a,int b)
{
    return a + b;
}
//半缺省
int fun(int a,int b = 5)
{
    return a + b;
}
**//半缺省,只能从右往左缺省,该情形错误
int fun(int a = 5,int b)
{
    return a + b;
}**
//全缺省
int fun(int a = 1,int b = 5)
{
    return a + b;
}
//函数的重载                                                                                                                                        
//函数的重载与缺省参数的重载函数冲突时,会报错
int fun(int a)
{
    return a;
}

int main()
{
    //对于缺省的函数来说,如果有传实参,则使用实参,否则用默认的行参
    //调用全缺省或半缺省,当两者共存时,会发生错误
    //调用全缺省时:a = 1,b = 2
    //调用半缺省时:a = 1,b = 5
    cout<<fun(1,2)<<endl;
    //调用半缺省参数或只有一个int类型参数的重载函数,当二者并存时,会发生冲突
    cout<<fun(1)<<endl;
    return 0;
}     

注意:
(1)缺省参数只能从右往左连续设定
(2)对于缺省参数,若传递了实参,则用实参;若没有传递,则使用缺省参数
(3)当某些全缺省参数函数和半缺省参数函数以及函数重载发生冲突时,会报错。
(4)缺省参数不能在声明和定义中同时出现。在声明中出现了缺省参数,定义中就不能出现;在声明中没有出现缺省参数,则定义中可以出现(也可以不出现)。函数的使用按照声明的格式来调用。
(5)缺省参数的值可以使用宏和全局变量。

命字空间

命字空间域相当于一个文件域。它是用来解决全局命名冲突的问题的。

命字空间的定义:以关键字namespace开头声明一个命字空间,“{}”内表示命字空间中的内容。
std:存放标准C++库中的所有组件的命字空间

如:

namespace name1
{
    int a = 10;
}
namespace name2
{   
    int a = 20;
}

命字空间的使用方法:
(1)using namespace 名字空间名;(指定该名字空间为全局域)
(2)名字空间名::名字空间中的内容(“::”表示域作用解析符,用于指明使用哪个域)

如:
using namespace std; 表示程序中某些变量默认使用名字空间std中定义的变量。
name1::a:此时的a的值即为10,而不是20。

变量的访问规则:
1. 如果访问的变量没有指定名字空间域。
(1)如果在main中被定义为了局部变量,则遵循就近原则,访问该局部变量。

.......
int a = 20;
int main()
{
    int a = 10;
    cout<<a<<endl;//输出10
}

(2)如果没有,则访问定义的全局变量。如果定义了全局变量或者using指定的全局域中都有定义该变量,则发生冲突。

namespace name1
{
    int a = 10;
}
int a = 20;
using namespace name1;
int main()
{
    //此时会访问冲突,因为定义了全局变量a =20
    //又指定了全局域name1,name1中也有变量a
    cout<<a<<endl;
}

2 如果访问的变量指定了名字空间域
(1)如果显式指定了名字空间域,则根据指定的名字空间域进行查找,找不到则报错;如:

namespace name1
{
    int a = 10;
}
int a = 20;
int main()
{
    int a = 30
    //此时会访问name1中的变量a,所以a为10;
    //如果没有定义名字空间name1或者name1中没有定义变量a,则出错
    cout<<name1::a<<endl;
}

(2)如果访问的变量形式”::a”,此时表示的是在全局域中访问a;对于a的访问遵循以下规则:
i)如果有全局变量,则访问全局变量a;
ii)如果没有全局变量a,则在全局域(using指定的全局域)中访问a,如果没有全局域或者全局域中没有变量a,则出错;如果using指定了多个全局域,若多个全局域中有多个a,则冲突出错;如果多个全局域中只有一个定义了a,则访问a;如:

.......
namespace name1
{
    int a = 10;
}
namespace name2 
{
    int a = 20;
}
using namespace name1;
using namespace name2;
int a = 30;
int main()
{
    cout<<::a<<endl;//此时访问全局变量a=30
}
.......
namespace name1
{
    int a = 10;
}
namespace name2 
{
    int a = 20;
}
using namespace name1;
using namespace name2;
int main()
{
    //此时访问冲突
    cout<<::a<<endl;
    //若全局域只指定了name1或者只指定了name2,则访问相应的全局域
}

注意:
1. using可以指定多个名字空间,只要访问的变量不在多个名字空间中存在即可;
2.命字空间可以嵌套定义,访问时也要嵌套访问。

  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值