初识C++——命名空间,缺省参数,函数重载


前言

随着编程的学习,我们到达可以学习C++的水平。从今天开始,将全面的学习C++,从入门,到入土。


一、命名空间

#include<stdio.h>
#include<stdlib.h>
int rand=5;
int main()
{

	printf("%d\n", rand);
	// ::域作用限定符
	return 0;
}

当我们在运行上述代码时,会报错。

因为在定义变量时,我们无法在同一个域内定义两个名称相同的变量。
而在#include<stdlib.h>中,已经有了一个名为rand的函数,所以我们不能再定义一个名为rand的变量。这时常使我们感到困扰,而在C++中,新创了命名空间,来改变这一现状。

#include<stdio.h>
#include<stdlib.h>
namespace N1{
	int rand=5;
} 
int a=5;
int main()
{
	int a=0;
	printf("%d\n", a);//输出为函数内变量a
	printf("%d\n", ::a);//输出为函数外变量a,::前无名称,则访问全局
	printf("%d\n", N1::rand);
	// ::域作用限定符
	return 0;
}

(::)用于改变访问顺序
不加时,在寻找名称时,先在函数内寻找,找不到再去函数外。
增加后,直接去指定域寻找。

在此,我们在头文件中开辟了一段空间,用于存储我们所需要定义的,有可能与库中函数名重复的一系列变量名与函数名。
而在使用时,需要像: printf(“%d\n”, N1::rand); 一样,在变量前,加一操作符,用于专门访问该空间。

命名空间的存在,就好像在仓库中,建立了一个带锁的箱子,虽然它也处于仓库(头文件)中,但由于其上了锁,所以平常我们在浏览仓库时,并不会去箱子中查找,箱子里的东西,也不会和仓库的其他东西相互影响。
当我们需要使用时,只需带上钥匙( spacename::)即可。

而c++也由此,开辟了自己的库std。

#include <iostream>
int main()
{
	std::cout << "hello world" << std::endl;
	std::cout << "hello world" << std::endl;
	std::cout << "hello world" << std::endl;
	return 0;
}

但我们发现,每一次调用c++库中的函数,都要加前置std::,这对于一些需要经常使用的函数(cout,cin)来说,是非常不方便的。

于是,又有了using namespace,我们可以将这个上锁的箱子打开,所有箱中事物任你调用。

#include <iostream>
using namespace std;
//无法 int cout;
int main()
{
	cout << "hello world" << endl;
	cout << "hello world" << endl;
	cout << "hello world" << std::endl;

	return 0;
}

但此时,命名冲突的问题又出现了。
于是,using std::cout;就诞生了,它可以只将std中指定函数open。

#include <iostream>
using std::cout;
int endl;
int main()
{
	cout << "hello world" << std::endl;
	cout << "hello world" << std::endl;
	std::cout << "hello world" << std::endl;
	return 0;
}

在不同.h,.cpp文件中命名相同的namespace会在使用时自动合并。
有趣的是在namespace中,我们还可以namespace,无线套娃。

#include<stdio.h>
#include<stdlib.h>
namespace N1{
	int rand=5;
	namespace N2{
					int a=3;
				}
} 
int a=5;
int main()
{
	int a=0;
	printf("%d\n", a);//输出为函数内变量a
	printf("%d\n", ::a);//输出为函数外变量a,::前无名称,则访问全局
	printf("%d\n", N1::rand);
	printf("%d\n", N1::N2::a);//其先找N1,再在N1中找N2,再找a
	// ::域作用限定符
	return 0;
}

通过灵活利用命名空间与它的打开,我们可以很好地解决C中无法定义与函数名重复的变量名称问题,也就是解决了命名冲突。

二、缺省参数

1.作用

void Func(int a = 0)
{
	cout << a << endl;
}
int main()
{
	Func();
	Func(5);
	renturn 0;
}

缺省参数就是我们在定义函数时,可以为形参赋值。当我们在调用这些函数时,如果未给值,则函数会使用提前赋的值运行。

void SLInit(ST* ps, int defaultCP=4)
	{
		ps->a = (int*)malloc(sizeof(int)*defaultCP);
		assert(ps->a);
		ps->size= 0;
		ps->capaicty = defaultCP;
	}

上面这个函数,大家应该很熟悉,它是我们用缺省参数写的顺序表初始化函数。在之前写初始化函数时,我们要么不给它开辟空间,要么只能开辟固定空间。

其坏处在于:当我们知道数据个数时,无法灵活做出改变,只能看着它在插入数据时不断开辟新空间,这实际上是非常低效的。

而使用缺省参数修改后,在我们不清楚数据个数时,只需和以前一样使用,若知道个数,则可在传参时,加入数据个数,提高整体运行效率。

2.使用规范

缺省参数分为2种
全缺省:

void f(int a=3,int b=4,int c=5)
{
cout<<a<<b;
}
int main()
{
f(3);//正确
f(3,4);//正确
//f(3, ,4);错误
return 0;
}

调用时,不能跳跃赋值。

部分缺省:

void f(int a,int b=4int c=5)
{
cout<<a<<b;
}
//void f(int a,int b=4,int c)定义时,只能从右向左缺省,不能跳跃
//{
//cout<<a<<b;
//}

调用同全缺省。

其还规定了对于若函数的声明与定义要分开,则只能存在一个缺省参数。

void f(int a,int b=4int c=5);
void f(int a,int b,int c)
{
cout<<a<<b;
}

原因是当声明与定义的缺省参数不同时,会产生二义性。
所以其规定只能在函数的声明中使用。

缺省参数的使用,使我们的函数更加灵活,提高效率

三、函数重载

1.作用与使用

int addi(int a,int b)
{
return a+b;
}

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

对于add函数,不同类型的变量,我们要定义不同的函数,而由于函数名不能重复,我们就要在add后加上许多后缀,显得十分麻烦,也在使用时给我们带来了许多困扰。

int add(int a,int b)
{
return a+b;
}

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

函数重载就是允许函数定义相同的函数名,但参数要在类型或个数上相互不同。
其好处在于,我们可以定义多个add,用于适应不同类型的数值操作。而在使用时,又好像在使用同一函数,可以给予不同的初始条件(参数), 来处理相同的事情。

int main()
{
int a=add(1,2);
double b=add(1.3+2.0);
}

简单介绍其本质:
在这里插入图片描述
我们都知道,C语言中,函数名存放在符号表中,然后在我们调用函数时,通过在符号表中检索函数名,再找到其对应地址,再调用。
而C++在存储这些函数名时,对其命名方式采用函数名+参数类型(不同编译器里,参数类型有其自己的映射),称作函数名修饰规则

加餐
函数重载是通过参数个数的不同或类型的不同来区分的,那为什么不能通过返回值类型不同来区分。

int add(double a,double b)
{
returnint(a+b);
}
double add(double a,double b)
{
return a+b;
}

其实很简单,对于上面两个函数,由于其只有返回值类型的差异。
所以,我们在调用时,会造成二义性,即编译器不知道调用哪一个。
c++的设计者们早就想到了这一点,所以未将返回值不同加入函数名修饰规则中。

2.与缺省同时使用

void f(int a=4,int b=5)
{
cout>>a;
}

void f()
{
cout>>"4";
}

首先,上面两个函数构成函数重载。
而在调用时:
仅在使用f()时,会出现二义性。
在使用f(4)或f(3,2)都没问题。


总结

此时,我们成功进入了C++入门的入门。
见识到了,C++对C的部分改造,相信一起认真学习,我们都会成为优秀的C++工程师。
祝大家前程似锦。

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值