C++命名空间、输入输出、函数缺省参数、函数的重载

引言

        详细介绍C++中的知识点:命名空间C++的输入输出C++中的(C语言中没有)函数缺省参数函数的重载

一、命名空间

1、namespace的价值

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

看个案例: 

#include<stdlib.h>
#include<stdio.h>

int rand = 10;
int main()
{
	printf("%d \n", rand);
	return 0;
}

运行这段代码,编译器会报错:

rand是一个库函数,这里又给rand定义为int型,导致rand重定义了,编译会报错。

为了解决这样的问题,C++中引入了命名空间的概念

2、namespace的定义

• 定义命名空间,需要使用到namespace关键字,后面跟命名空间的名字,然后接一对{}即可,{}中即为命名空间的成员。命名空间中可以定义变量 / 函数 / 类型等。

namespace test
{
	int a = 10;
	int Add(int a, int b)
	{
		return a + b;
	}
	int rand;
}

 • namespace本质是定义出一个域,这个域跟全局域各自独立,不同的域可以定义同名变量,所以下面的rand不在冲突了。

在 C++ 里,:: 是作用域解析运算符,其作用是明确指定要使用的变量、函数或者类属于哪个命名空间或者类。大白话就是:使用该命名空间里面的东西。

#include<iostream>
namespace test
{
	int a = 10;
	int Add(int a, int b)
	{
		return a + b;
	}
	int rand = 20;
}


int main()
{
	printf("%d \n", test::rand);
	return 0;
}

C++中域有函数局部域,全局域,命名空间域,类域;域影响的是编译时语法查找⼀个变量 / 函数 / 类型出处(声明或定义)的逻辑,所以有了域隔离,名字冲突就解决了。局部域和全局域除了会影响编译查找逻辑,还会影响变量的生命周期,命名空间域和类域不影响变量生命周期。 

• namespace只能定义在全局,当然他还可以嵌套定义。

namespace test
{
	int a = 10;
	int Add(int a, int b)
	{
		return a + b;
	}
	int rand = 20;
	namespace test01
	{
		int a = 29;
		int Add(int a, int b)
		{
			return a - b;
		}
	}
}
int main()
{
	printf("%d \n", test::rand);
	printf("%d \n", test::a);
	printf("%d \n", test::test01::a);
	printf("%d \n", test::Add(1, 2));
	printf("%d \n", test::test01::Add(1, 2));
	return 0;
}

 

• 项目工程中多文件中定义的同名namespace会认为是一个namespace,不会冲突。

• C++标准库都放在⼀个叫std(standard)的命名空间中。

3、命名空间的使用 

编译查找⼀个变量的声明 / 定义时,默认只会在局部或者全局查找,不会到命名空间里面去查找。所以下面程序会编译报错。所以我们要使用命名空间中定义的变量 / 函数,有三种方式:

• 指定命名空间访问,项目中推荐这种方式。(即通过::来访问命名空间里的)

在 C++ 里,:: 是作用域解析运算符,其作用是明确指定要使用的变量、函数或者类属于哪个命名空间或者类。大白话就是:使用该命名空间里面的东西。

• using将命名空间中某个成员展开,项目中经常访问的不存在冲突的成员推荐这种方式。

#include<iostream>
namespace test
{
	int a = 10;
	int Add(int a, int b)
	{
		return a + b;
	}
	int rand = 20;
	namespace test01
	{
		int a = 29;
		int Add(int a, int b)
		{
			return a - b;
		}
	}
}

using test::a; //将a展开,全局可用
int main()
{
	a = 20;

	return 0;
}

• 展开命名空间中全部成员,项目不推荐,冲突风险很大,日常小练习程序为了方便推荐使用。

namespace test
{
	int a = 10;
	int Add(int a, int b)
	{
		return a + b;
	}
	int rand = 20;
	namespace test01
	{
		int a = 29;
		int Add(int a, int b)
		{
			return a - b;
		}
	}
}
using namespace test; //将test里面的所以内容全部展开,可作用全局
int main()
{
	a = 20;
	Add(1, 2);

	return 0;
}

二、C++输入&输出

• 是InputOutputStream的缩写,是标准的输入、输出流库,定义了标准的输入、输出对象。

• std::cin 是istream类的对象,它主要面向窄字符(narrowcharacters(oftypechar))的标准输 入流。

• std::cout 是ostream类的对象,它主要面向窄字符的标准输出流。

• std::endl 是⼀个函数,流插入输出时,相当于插入⼀个换行字符加刷新缓冲区。

• << 是流插入运算符,>>是流提取运算符。 (C语言还用这两个运算符做位运算左移 / 右移)

• 使用C++输入输出更方便,不需要像printf/scanf 输入输出时那样,需要手动指定格式,C++的输入输出可以自动识别变量类型 (本质是通过函数重载实现的),其实最重要的是 C++的流能更好的支持自定义类型对象的输入输出。

• IO流涉及类和对象,运算符重载、继承等很多⾯向对象的知识,所以这⾥只是简单认识一下C++IO流的用法,后面会有专门来细讲 IO 流库。

• cout / cin / endl等都属于C++标准库,C++标准库都放在⼀个叫std(standard)的命名空间中,所以要通过命名空间的使用方式去用他们。

• ⼀般日常练习中我们可以 using  namespace  std,实际项目开发中不建议。

• 没有包含<stdio.h>,也可以使用 printf 和 scanf,在包含< stdio.h> 间接包含了。vs系列编译器是这样的,其他编译器可能会报错。

cin / cout 可以自动识别数据的类型

#include<iostream>
using namespace std;

int main()
{
	int a = 10;
	double b = 20.2;
	char c = 'x';
	cout << a << " " << b << " " << c << endl;
	cout << endl;
	cin >> a >> b >> c;
	cout << a << " " << b << " " << c << endl;
	return 0;
}

        在 io 需求比较高的地方,如部分大量输入的竞赛题中,加上以下 3 行代码,可以提高 C++IO 效率(这里只是提一下):

#include<iostream>
using namespace std;
int main()
{
	ios_base::sync_with_stdio(false);
	cin.tie(nullptr);
	cout.tie(nullptr);

	return 0;
}

 三、缺省参数

• 缺省参数是声明或定义函数时为函数的参数指定一个缺省值。在调用该函数时,如果没有指定实参则采用该形参的缺省值,否则使用指定的实参,缺省参数分为全缺省和半缺省参数。(有些地方把缺省参数也叫默认参数)

#include<iostream>
using namespace std;

void Fun(int a = 20) //给一个默认的值,没有传过来a的话,就使用默认值
{
	cout << a << endl;
}


int main()
{
	Fun(); //打印:20    没有传参使用默认值
	Fun(10); //打印:10

	return 0;
}

• 全缺省就是全部形参给缺省值,半缺省就是部分形参给缺省值。C++规定半缺省参数必须从右往左 依次连续缺省,不能间隔跳跃给缺省值。

• 带缺省参数的函数调⽤,C++规定必须从左到右依次给实参,不能跳跃给实参。

#include<iostream>
using namespace std;

void Fun1(int a = 1, int b = 2, int c = 3) //全缺省
{
	cout << a << " " << b << " " << c << endl;
}

void Fun2(int a, int b = 20, int c = 30) //半缺省
{
	cout << a << " " << b << " " << c << endl;
}
int main()
{
	Fun1();  // 1 2 3
	Fun2(1); // 1 20 30 半缺省,必须传入没有缺省的变量的值
	Fun2(1, 4); //1 4 30
	Fun2(1, 4, 5); // 1 4 5
	return 0;
}

• 函数声明和定义分离时,缺省参数不能在函数声明和定义中同时出现,规定必须函数声明给缺省 值。(避免函数声明和定义时的缺省参数的值不一样)

正确示例:

在Add.cpp中(定义):

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

在Add.h中(声明):

int Add(int a = 10, int b = 20);

在test.cpp中测试:

#include<iostream>
#include"Add.h"
using namespace std;

int main()
{
	int ret = Add();
	cout << ret << endl; //30
	return 0;
}

四、函数重载

        C++支持在同⼀作用域中出现同名函数,但是要求这些同名函数的形参不同,可以是参数个数不同或者 类型不同。这样C++函数调用就表现出了多态行为,使用更灵活。C语言是不支持同⼀作用域中出现同名函数的。

1、参数类型 / 顺序不同 

#include<iostream>
using namespace std;

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

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

double Add(double a, double b)
{
	return a + b;
}
int main()
{
	cout << Add(1, 1) << endl;   // 2
	cout << Add(1.2, 1) << endl; // 2.2
	cout << Add(1.3, 1.3) << endl; // 2.6
	return 0;
}

2、参数个数不同

#include<iostream>
using namespace std;
int Add(int a, int b)
{
	return a + b;
}

int Add(int a, int b, int c)
{
	return a + b + c;
}

int main()
{
	cout << Add(1, 1, 2) << endl; //4
	cout << Add(1, 1) << endl;     //2
	return 0;
}

3.注意:

        返回值不同,不能作为函数重载的条件

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值