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

1. 命名空间
在C/C++中,变量、函数和类都是大量存在的,这些变量、函数和类的名称将都存在于全局作用域中,可能会导致很多冲突。作用域分三种: 全局域, 局部域和文件域 . 使用命名空间的目的是对标识符的名称进行本地化,以避免命名冲突或名字污染,namespace关键字的出现就是针对这种问题的。

//1. 普通的命名空间
namespace N1{// N1为命名空间的名称
	// 命名空间中的内容,既可以定义变量,也可以定义函数
	int a;
	int Add(int left, int right){
		return left + right;
 	}
}
//2. 命名空间可以嵌套
namespace N2{
	int a;
	int b;
	int Add(int left, int right){
			return left + right;
	}
	namespace N3{
		int c;
		int d;
		int Sub(int left, int right){
			return left - right;
 		}
 	}
}
//3. 同一个工程中允许存在多个相同名称的命名空间,编译器最后会合成同一个命名空间中。所以不要定义重复的变量和函数
namespace N1{
	int Mul(int left, int right){
		return left * right;
 	}
}

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

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

  1. 加命名空间名 + 作用域限定符 + 成员
  2. 使用using将命名空间中成员引入, using + 命名空间 + :: +成员 , 后面使用成员时, 不需要再加作用域了, 相当于暴露在全局当中,如果全局中有同名成员, 会导致命名冲突.
  3. 使用using namespace + 命名空间名称引入, 将命名空间中所有成员全部暴露在全局域中

最推荐的是第一种方式, 也体现了命名空间的初衷, 就是把命名空间的成员与其他作用域 的成员区分开来, 就算出现同名的成员, 编译器也能唯一确定这个成员是哪个命名空间的. 后面两种方式都会产生命名冲突的问题.

//全局域
//int  global = 10;
int fun(){
	//局部域
	int a = 1;
	return a;
}
//文件域
static void fun2(){
}

void testNamespace(){
	//全局域: 命名空间可以没有名字
	::global = 10;
}
using namespce N; // 使用using namespace 命名空间名称引入
// using N::b; 使用using将命名空间中成员引入
int main()
{
 	printf("%d\n", N::a); // 加命名空间名称及作用域限定符
 	printf("%d\n", b);// 直接使用
 	Add(10, 20);
 	return 0; 
}

2. 缺省参数
2.1 概念
缺省参数是声明或定义函数时为函数的参数指定一个默认值。在调用该函数时,如果没有指定实参则采用该默认值,否则使用指定的实参。声明或者定义,只能选其一给默认值

void TestFunc(int a = 0){ //默认值
	cout<<a<<endl; 
}
int main(){
	TestFunc(); // 没有传参时,使用参数的默认值0
	TestFunc(10); // 传参时,使用指定的实参10
}

2.2 分类

默认值就像备胎,未指定参数时,默认值就上;指定参数时, 默认值就退下

  • 全缺省参数(参数全部都有默认值)
void TestFunc(int a = 10, int b = 20, int c = 30){
	cout<<"a = "<<a<<endl;
	cout<<"b = "<<b<<endl;
	cout<<"c = "<<c<<endl; 
}
  • 半缺省参数(部分参数没有设置默认值)
void TestFunc(int a, int b = 10, int c = 20){
	cout<<"a = "<<a<<endl;
	cout<<"b = "<<b<<endl;
	cout<<"c = "<<c<<endl; 
}

注意:

  • 半缺省参数必须从右往左依次来给出,不能间隔着给
  • 缺省参数不能在函数声明和定义中同时出现, 如果声明与定义位置同时出现,恰巧两个位置提供的值不同,那编译器就无法确定到底该用哪个缺省值
  • 缺省值必须是常量或者全局变量
  • C语言不支持(编译器不支持)

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

  • 前提: 多个函数在同一个作用域下(同一个系列的不同版本的手机, 都是iphone)
  • 函数名相同 可以参数信息(个数, 参数类型, 参数顺序)不同,
int Add(int left, int right){
	return left+right; 
}
double Add(double left, double right){
	return left+right; 
}
long Add(long left, long right){
	return left+right; 
}
int main(){
	Add(10, 20);
	Add(10.0, 20.0);
	Add(10L, 20L);
 
	return 0; 
}

C语言没办法支持重载,因为同名函数没办法区分。而C++是通过函数修饰规则来区
分,只要参数不同,修饰出来的名字就不一样,就支持了重载。

 C编译器: int sub(int,int)   底层的函数名为_sub
 C++编译器: int sub(int, int)  底层的函数名为...(不认识)
 g++编译器: int sub(int, int)  底层的函数名为 _Z3subii, 3为函数名长度, 后面的ii为参数类型(i,f,c)
 C编译器函数名的修饰规则: 只包含函数名
 C++编译器函数名的修饰规则为: 函数名+参数信息(顺序, 个数, 类型) 
 导致C++支持函数重载, C不支持
 
链接:
 文件之间的交互, 汇编阶段产生导出符号表和未解决符号表(函数名和起始的位置) 链接的时候去其他文件中找
// 预处理: 头文件展开, 去注释, 条件编译, 宏替换
// 编译: 语法检查, 把源代码编译成汇编代码
// 汇编: 把汇编代码编译成机器码 --> 目标文件(.o, .obj), --> 导出符号表 ,未解决符号表
// 链接: 把所有的机器码转换成一个可执行文件, --> 找到所有指令的地址


a.cpp
int funa(int a, int b){}
 生成.obj文件, 还有导出符号表: funa, 0X45(地址)
 未解决符号表: 空

#include "a.h"
b.cpp
int funb(int a){}
int main(){
	funa(1, 2);
	funb(3);
}
生成b.obj
导出符号表: funb 0X63(地址)
未解决符号表: funa?(去找funa的地址, 从而找到funa的所有

有时候在C++工程中可能需要将某些函数按照C的风格来编译,在函数前加extern “C”,意思是告诉编译器,将该函数按照C语言规则来编译。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值