C++入门

本文介绍了C++中的命名空间用于解决命名冲突问题,提供了三种使用方式。接着讨论了函数重载的概念,展示了不同参数个数、类型和顺序如何实现重载。此外,文章还讲解了引用作为参数和返回值的用法,以及内联函数的作用和注意事项。


C++,全称:C Plus Plus,它是在C语言的基础上不断加东西加出来的,所以C++兼容于C。
而这篇文章呢,就说说它加了些什么东西:

命名空间

首先,我们来看看一段C代码:

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

int rand = 1;

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

这个代码很简单,很容易就看出输出10,但是如果把第二个头文件取消注释,就会发现编不过,会提示rand重定义,那我们还非得改个名字?
这个当然是小问题,但是如果在项目里面,不同人写不同代码,在各自的编译器上还通得过,合并到一起就通不过了,发现变量名相同,遇到一次改一次,很麻烦,所以,C++就在C的基础上加了个东西叫做命名空间。
把写的代码都放到命名空间里面去:

namespace xxx
{
	int a = 10;
	
	int add(int x, int y)
	{
		return x + y;
	}
}


int main()
{
	int num = xxx::add(2, 3);//:: 叫做域操作限定符
	return 0;
}

这里我把变量a和add函数都放在一个xxx的空间里面,如果要调用这个函数或者a这个变量,就要在这个命名空间里面去找,一个命名空间定义一个作用域。

另外,命名空间是可以嵌套调用的,命名空间里面还可以定义一个新的命名空间。
并且,如果两个命名空间的名字是一样的,那么编译器会把它们当成同一块命名空间。

命名空间的使用

加命名空间名字和作用域操作符

上面那个例子用的就是这个方法,这个方法是指定访问,它不会访问其他的内容,并且调用一次就要写一次。

使用命名空间某个成员引入

namespace xxx
{
	int a = 10;
	
	int add(int x, int y)
	{
		return x + y;
	}
}

using xxx::a;
int main()
{
	printf("%d\n", a);//输出10
	return 0;
}

这个方法是部分展开,就是把命名空间里面的变量a在全局展开,可以理解为a就是一个全局变量,用这个方法就不需要用一次写一次了。

使用using namespace命名空间引入

namespace xxx
{
	int a = 10;
	
	int add(int x, int y)
	{
		return x + y;
	}
}

using namespace xxx;

int main()
{
	int num = add(a, 3);
	printf("%d\n", num);
	return 0;
}

这个方法就是把整个命名空间在全局展开,是全部展开,如果两个命名空间里面有一样的变量,全部展开相当于定义了两个一样的变量,还是会报错。

输入输出

C++的输入输出和C的不一样:

#include<iostream>

using namespace std;

int main()
{
	cout << "hello world" << endl;
	int x = 0;
	cin >> x;
	cout << x << endl;
	return 0;
}

cout :标准输出对象(控制台)
cin :标准输入对象(键盘)
使用这两个需要包含头文件#include,以及std,std就是C++的标准库命名空间。
C++的输入输出并不需要指定数据格式,它会自动识别类型。

缺省参数

概念

缺省参数就是在声明或者定义函数为参数给定一个缺省值,如果在调用该函数时有给定值则用给定的值,没有给值则默认用缺省值。

分类

全缺省参数

顾名思义就是,所有的参数都有缺省值:

#include<iostream>

using namespace std;

void Print(int x = 1, int y = 1)
{
	cout << "x=" << x << " " << "y=" << y << endl;
}

int main()
{
	Print(2, 3);
	Print();
	return 0;
}

半缺省参数

这个就是给定一部分的缺省值。

#include<iostream>

using namespace std;

void Print(int x, int y = 1)
{
	cout << "x=" << x << " " << "y=" << y << endl;
}

int main()
{
	Print(2, 3);
	Print(3);
	return 0;
}

这个缺省参数给缺省值必须从右往左开始,不能隔着给。
另外还有一点补充:缺省参数声明和定义不能同时给缺省值,因为如果都给了,编译器不能该用哪个缺省值,一般我们是在声明位置给。

函数重载

在C++中函数名称可以相同,只要函数参数个数不同,类型不同,顺序不同,满足任意一点则可以构成函数重载。

函数参数个数不同

#include<iostream>

using namespace std;

void func(int a, int b)
{
	cout << a << " " << b << endl;
}

void func(int a)
{
	cout << a << endl;
}

int main()
{
	func(2, 3);
	func(2);
	return 0;
}

类型不同

#include<iostream>

using namespace std;

void func(int a, int b)
{
	cout << a << " " << b << endl;
}

void func(int a, double b)
{
	cout << a << " " << b <<endl;
}

int main()
{
	func(2, 3.01);
	func(2, 2);
	return 0;
}

顺序不同

#include<iostream>

using namespace std;

void func(int a, double b)
{
	cout << a << " " << b << endl;
}

void func(double a, int b)
{
	cout << a << " " << b << endl;
}

int main()
{
	func(3.01,2);
	func(2, 2.01);
	return 0;
}

那为什么C语言不能构成函数重载,而C++可以?
那是因为C++多了一个函数命名修饰规则,在C语言中,调用函数是找函数名,没找到就会产生链接错误,而C++通过函数命名规则,把函数名进行修饰之后,再通过修饰之后的名称去调用。
函数怎么修饰的?
这里我们用Linux系统来举例:
它修饰是以“_Z + 函数长度+ 函数名 + 类型首字母”格式来进行修饰的。
我们来看看上面三种情况函数名修饰之后是什么样子:

函数参数个数不同: _Z4funcii _Z4funci
类型不同: _Z4funcii _Z4funcid
顺序不同: _Z4funcid _Z4funcdi

看到这里就会发现只要上面三种情况任意一种情况函数修饰之后函数名都不相同,所以才能构成函数重载。

引用

这个相当于给某个变量起了个外号,所以不会额外开空间。

#include<iostream>

using namespace std;

int main()
{
	int a = 2;
	int& b = a;

	b++;

	cout << a << endl;
	cout << b << endl;
	return 0;
}

这里b是a的取别名,此时,b和a指向的是同一块空间,不会额外开空间,改变b或者a,另一个变量也会跟着改变,有一点要注意,就是给变量取了别名,这个别名类型要和这个变量类型是一样的。

引用的特性:
引用在定义时必须初始化。
一个变量可以有多个引用。
引用一旦引用一个实体,就不能再引用其他实体。

补充:

int main()
{
	const int a = 2;
	//int& b = a;//编译错误,因为a被const修饰,是常变量,具有常量的属性,所以是只有只读权限,而给a取别名之后,就是一个可以修改的变量了,权限放大
	const int& b = a;//所以也需要在b前面加上const修饰

	//int& c = 10;//同样10就是一个常量,需要在前面加长const
	const int& c = 10;

	double d = 3.14;
	//int& e = d;//把double转换成int类型,是会先产生临时变量,然后再转换的,而临时变量具有常性,所以加上const就可以
	const int& e = d;
	return 0;
}

使用场景:

作参数

void Swap(int& a, int& b)
{
	int c = a;
	a = b;
	b = c;
}

int main()
{
	int x = 3;
	int y = 4;

	cout << x << endl;
	cout << y << endl;

	Swap(x, y);

	cout << x << endl;
	cout << y << endl;
	return 0;
}

作返回值

int& Add(int a, int b)
{
	static int c = 1;//静态变量存储在全局区,出了作用域不会销毁
	c = a + b;

	return c;
}

int main()
{
	int& ret = Add(2, 3);

	cout << ret << endl;
	return 0;
}

现在看看下面这段代码,有什么问题吗?

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

int main()
{
	int& ret = Add(2, 3);
	cout << ret << endl;
	return 0;
}

输出结果是未定义的,Add函数中的变量c是临时变量,出了作用域就销毁了,这个销毁不是没有这块空间了,而是这块空间还给操作系统了,不再属于自己的了,函数返回值是c这块空间,至于返回之后这块空间有没有被动过是不确定的,没动过就是5,动过就是随机值。

内联函数

以inline修饰的函数叫做内联函数,它和C语言的宏函数差不多,编译期间直接在内联函数调用的地方展开,不会建立函数栈帧,提升程序运行的效率。
但是如果调用次数较多,会使目标文件变大,所以它是一个以空间换时间的方式。
inline对于编译器只是一个建议,编译器可以忽略,一般函数体不是很长,并且这个函数不会频繁调用或者递归调用才采用inline修饰。

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

int main()
{
	int num = Add(2, 3);
	cout << num << endl;
	return 0;
}

inline函数不建议声明和定义分开,因为在经过预编译处理之后被展开,就没有函数地址了,会产生链接错误。

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值