初识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++工程师。
祝大家前程似锦。

  • 4
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
在C语言中,unordered_set的函数包括: - begin():返回一个迭代器,指向unordered_set的第一个元素。 - end():返回一个迭代器,指向unordered_set的末尾(最后一个元素的下一个位置)。 - insert(const K& key):将一个元素插入到unordered_set中,并返回一个pair对象,其中的iterator指向插入的元素,bool值表示是否插入成功。 - find(const K& key):查找unordered_set中是否存在指定的元素,如果找到,则返回一个指向该元素的迭代器;如果找不到,则返回end()。 - erase(const K& key):从unordered_set中删除指定的元素,如果删除成功,则返回true;如果删除失败(即元素不存在),则返回false。 需要注意的是,在C语言中,unordered_set的函数并不是直接在C标准库中提供的,而是通过自定义的unordered_set类实现的。所以,使用unordered_set函数之前,需要先引入相应的头文件,并使用对应的命名空间。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* *2* [初识C++之unordered_map与unordered_set](https://blog.csdn.net/Masquerena114514/article/details/129938734)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 50%"] - *3* [c++ unordered_set 函数参考](https://blog.csdn.net/weixin_46183779/article/details/119979647)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 50%"] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值