【C++入门第一期】命名空间 缺省参数 函数重载 的使用方法及注意事项

简介

经过许久的C语言学习,前不久终于开始了c++的学习经过总结写下了这篇文章.
总结:C++总计63个关键字,C语言32个关键字
在这里插入图片描述
废话少说直接开始第一个知识点

命名空间

首先按照学习一门语言的惯例写一段 Hello world 入门代码.
在这里插入图片描述
刚开始学能你不清楚为什么我只打印一句 Hello world 包含头文件我理解但为啥还要带一句 using namespace std 。有人可能表示这是命名空间书上说过,对大致上可以这么理解。

但是你知道他为啥要这么定义吗?定义规则是什么吗?自己该如何定义吗?

如果都知道,很高兴的和你说您可以跳过本篇这个知识点了

为何会有命名空间

一个组,一起开发一个大型项目。但是他们但他们编写程序时就可能出现重名的函数,变量,结构体等,合并时就出现问题了大量的命名冲突。最初,人们就想了个办法,将名字取得更长更复杂来避免重复,可这样做却给编写和阅读带来了困难。后来,人们创造了命名空间这个概念,它能有效地指出某个标示符到底属于哪个库。

命名空间的定义

定义命名空间,需要使用到namespace 关键字,后面跟命名空间的名字,然后接一对{ }即可,{ }中即为命名空间的成员

如下 zgb 是命名空间的名字,大括号中的 sum 变量和 Add 函数及结构体 book 是 zgb 空间的成员

namespace zgb
{
    
    
	int sum = 10;
	int Add(int x, int y)
	{
    
    
		return x + y;
	}
	struct book
	{
    
    
		char name[15];
	}mm;
}

嵌套定义

可如下嵌套定义命名空间

namespace binbang
{
    
    
	int a = 29;
	namespace binbin
	{
    
    
		int Add(int x, int y)
		{
    
    
			return x + y;
		}
	}
}

命名空间相同时如相互的成员名均不同则会合并相同的命名空间,但成员名相同时则会发生命名冲突从而报错。
在这里插入图片描述
在这里插入图片描述
总结:
1:命名空间中可以定义变量,函数,结构体等非常自由。
2:命名空间可以嵌套定义
3:注意若同一工程中,命名空间名字如果相同,相同空间名中的成员会合并为一个命名空间,但这就丧失了命名空间的作用,因为由于是合并而成的里面的命名可能冲突导致报错
4:只要命名空间名字不同,每个命名空间是互不干扰的就像局部变量一样

命名空间的使用

命名空间的使用有三种方式

作用域限定符

使用方法命名空间名 : : 该空间成员(变量函数结构体等),符号左边写命名空间名,右边写该该空间成员
举例如下:
在这里插入图片描述
嵌套时也是如图加作用域限定符即可
在这里插入图片描述

学会了使用现在咱验证一下不同命名空间同名变量是否会冲突,答案是不会。如图
在这里插入图片描述

using 将命名空间中某个成员引入

使用方法:using 命名空间名 : : 该空间成员

如下图, using bb::sum;等于是声明了 bb 中的变量 sum,后面可以不加作用域限定符即可直接使用。注意如果该语句在全局中则该声明全局有效,如该语句在局部则该声明局部有效
在这里插入图片描述

using namespace 将该空间所有成员引入

使用方法:using namespace 命名空间名称
作用:将该空间所有成员引入,如下面using namespace std,就是将命名空间 std 中的内容全部展开(声明/引入),其中就包括了cout 。所以可以之后cout可以直接使用;
在这里插入图片描述
注意:该命令如在全局中使用,那将使命名空间失去意义,如果全局中与 引入(声明/展开)成员同名的变量或函数等将发生冲突,不同命名空间均在全局或同一个局部空间使用using namespace 将该空间所有成员引入(声明/展开)时也可能发生冲突
在这里插入图片描述
using namespace,一般在刷题,测试及局部中使用比较合适,工程和全局中可控性太低

缺省参数

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

如下图,test7 函数中有一个缺省值 x = 10,当调用 test7 函数时传参为22则,x 等于22当调用 test7 函数时参数为空则 x 默认等于缺省值10
在这里插入图片描述

全缺省参数函数

概念:指函数的参数均为均有缺省值
如下

void test9(int x = 10, int  y = 20, int  z = 30)
{
    
    
	cout << x << endl;
	cout << y << endl;
	cout << z << endl;

}

半缺省参数函数

概念:指函数的部分参数有缺省值,注意参数必须从右往左连续缺省,简要记无缺省值参数不能在缺省值参数的右边
如下是半缺省参数函数

void test9(int x , int  y = 20, int  z = 30)
{
    
    
	cout << x << endl;
	cout << y << endl;
	cout << z << endl;

}

为啥说无缺省值参数不能在缺省值参数的右边呢?

如下无缺省值参数出现在缺省值参数的右边,程序直接报错了。因为函数传参时是从左到右一 一对应的不能跳过中间参数进行传参,所以没有缺省值的参数需要在右边并且连续,达到优先及易区分等目的。
在这里插入图片描述

如何给缺省值

在实际使用中.c文件中的函数须在.h中声明时,如果要声明的函数带缺省值,应在.h文件中给缺省值,定义函数时不用给缺省值,如果两个都给缺省值那编译器将会报错,因为不知道该用那个

如下编译器将会报错

//a.h     (.h文件)
void zgb(int a = 10);
// a.cpp (.cpp文件)
void zgb(int a = 20)
{
    
    }

因为声明都没有缺省值那,函数的缺省值又从何而来呢
正确方式

//a.h     (.h文件)
void zgb(int a = 10);
// a.cpp (.cpp文件)
void zgb(int a )
{
    
    }

总结:

  1. 半缺省参数必须从右往左依次来给出,不能间隔着给
  2. 缺省参数不能在函数声明和定义中同时出现
  3. 缺省值必须是常量或者全局变量
  4. C语言不支持(编译器不支持)

函数重载

函数重载的概念

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

函数重载的三种类型

1:函数参数类型不同

如下函数同名,但函数参数类型不同,如下当函数调用时传参为int 类型则会调用函数参数为int类型的Add函数,反之则调用参数为double类型的Add函数;

//函数重载
int Add(int x, int y)
{
    
    
	cout << "Add(int x, int y)" << endl;
	return x + y;
}
double Add(double x, double y)
{
    
    
	cout << "Add(double x, double y)" << endl;
	return x + y;
}
void tese2()//函数重载,函数参数类型不同
{
    
    
	Add(1, 2);//编译时就链接好了对应函数
	Add(1.3, 1.5);
}

2:参数个数不同

如下函数同名,但函数参数个数不同,如下当函数调用时只传一个参数则使用一个参数Add函数,当函数调用时传两个参数则使用两个参数Add函数。(当然传参与函数参数需相同)

int Add( int y, char x)
{
    
    
	cout << "Add( int y, char x)" << endl;
	return y;
}
int Add(int x)
{
    
    
	cout << "Add(int x)" << endl;
	return x;
}
void tese4()//函数重载,函数参数个数不同
{
    
    
	Add(1);
	Add(2, 4);
}

3:参数类型顺序不同

如下函数同名,但函数各参数类型顺序不同,如下当调用函数传参时参数1为 char 类型参数二为 int 类型,则会调用 int Add(char x, int y)

当调用函数传参时参数1为 int 类型参数二为 char 类型,则会调用 int Add( int y, char x)

int Add(char x, int y)
{
    
    
	cout << "Add(char x, int y)" << endl;
	return x;
}
int Add( int y, char x)
{
    
    
	cout << "Add( int y, char x)" << endl;
	return y;
}
void tese3()//函数重载,函数参数顺序不同
{
    
    
	Add('a', 1);
	Add(1, 'a');
}

分析与总结

1:为什么C++支持函数重载,而C语言不支持函数重载呢?
在C/C++中,一个程序要运行起来,需要经历以下几个阶段:预处理、编译、汇编、链接
在这里插入图片描述

  1. 实际项目通常是由多个头文件和多个源文件构成,而通过C语言阶段学习的编译链接,我们可以知道,【当前a.cpp中调用了b.cpp中定义的Add函数时】,编译后链接前,a.o的目标文件中没有Add的函数地址,因为Add是在b.cpp中定义的,所以Add的地址在b.o中。
  2. 所以链接阶段就是专门处理这种问题,链接器看到a.o调用Add,但是没有Add的地址,就会到b.o的符号表中找Add的地址,然后链接到一起
  3. 链接时,面对Add函数,链接接器会使用哪个名字去找呢?这里每个编译器都有自己的函数名修饰规则
  4. 由于Windows下vs的修饰规则过于复杂,而Linux下g++的修饰规则简单易懂,下面我会使用g++演示函数修饰后的名字。
  5. 通过下面我们可以看出gcc的函数修饰后名字不变。而g++的函数修饰后变成【_Z+函数长度+函数名+类型首字母】。

linux下函数修饰规则

首先看看采用C语言编译器编译后结果,如下图在linux下,采用gcc编译完成后,函数名字的修饰没有发生改变。
在这里插入图片描述
在看看采用c++编译器编译后的结果,如下图在linux下,采用g++编译完成后,除main函数外的函数名字的修饰发生改变,编译器将函数参数类型信息添加到修改后的名字中。
在这里插入图片描述

Windows下修饰规则

由于Windows下Vs编译时函数的修饰规则较为复杂还是直接看下图吧
在这里插入图片描述
对比Linux会发现,windows下vs编译器对函数名字修饰规则相对复杂难懂,但道理都是类似的,我们就不做细致的研究了。

总结

  1. 通过上述举例应该理解了C语言没办法支持重载,是因为同名函数没办法区分。而C++是通过函数修饰规则来区分,只要参数不同,修饰出来的名字就不一样,就支持了重载。
  2. 注意:如果两个函数函数名和参数是一样的,返回值不同是不构成重载的,因为调用时编译器没办法区分
  3. 重载函数在运行时被调用怎么找到对应函数?在程序链接时,每条函数调用指令就已经链接好了对应函数地址,所以运行时使用重载函数效率也不会降低。

C++入门第一期内容就这些了,下期会更新引用/内联函数/auot等

猜你喜欢

转载自blog.csdn.net/ZhuGeBin26/article/details/128678578
今日推荐