【C++入门】①

1. C++关键字

C++ 关键字是 C++ 语言定义的专用词,它们有特殊的意义和用途,不能作为变量名、函数名或任何其他标识符的名称。

因为是C++入门,所以我们就先了解一下C++关键字大概有哪些,后续再做详细解释,如下图。

在这里插入图片描述
ps: 比较重要的关键字都已经圈出来了。

2. 命名空间

2.1 命名空间定义

在C++中,命名空间(Namespace)是一种将标识符组织在一起的方式,用于防止名字冲突。它可以防止全局命名的冲突,让你的代码更容易维护,也可以帮助控制程序的可见性,避免在全局命名空间中引入不必要的名字。

例如以下代码:
在这里插入图片描述
可以看出上述代码编译出错,它的错误是所定义的变量跟库里的函数名冲突,所以编译失败,这时候C++引入的命名空间解决了这类命名冲突问题。下面给出命名空间的定义。

2.1.1正常的命名空间定义

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

例如:

namespace C
{
	//namespace中可以存在变量/函数/类型
	int rand = 0;
	int Add(int a, int b)
	{
		return a + b;
	}
	struct ListNode
	{
		int val;
		struct ListNode* next;
	};
}

2.1.2命名空间嵌套

命名空间是可以嵌套命名空间的。

例如:

//test.cpp
namespace C
{
	int rand = 0;
	int Add(int a, int b)
	{
		return a + b;
	}
	struct ListNode
	{
		int val;
		struct ListNode* next;
	};

	namespace CB
	{
		int a = 0;
		int Minus(int a, int b)
		{
			return a - b;
		}
		struct LNode
		{
			int val;
			struct LNode* next;
		};
	}
}

int main()
{
	printf("%d\n", C::CB::a);
	return 0;
}

打印结果:

在这里插入图片描述

2.1.3多个名字相同的命名空间

在同一个工程中,允许存在多个相同名称的命名空间,编译器最后会合成同一个命名空间中。

//test.h
namespace C
{
	int b = 0;
}

ps: 一个工程中的test.h和上述test.cpp中两个C会被合并成一个。

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

2.2 命名空间的使用

命名空间的使用有三种方法:

  • 加命名空间名称及作用域限定符(::)

在这里插入图片描述

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

在这里插入图片描述

  • 使用using namespace 命名空间名称 引入

在这里插入图片描述

3. C++输入与输出

我们先看一下例子:

#include<iostream>
// std是C++标准库的命名空间名,C++将标准库的定义实现都放到这个命名空间中
using namespace std;
int main()
{
cout<<"Hello world!!!"<<endl;
return 0;
}

说明:

  1. 使用cout标准输出对象(控制台)cin标准输入对象(键盘)时,必须包含< iostream >头文件以及按命名空间使用方法使用std。
  2. cout和cin是全局的流对象,endl是特殊的C++符号,表示换行输出,他们都包含在包含< iostream >头文件中。
  3. <<是流插入运算符>>是流提取运算符
  4. 使用C++输入输出更方便,不需要像printf/scanf输入输出时那样,需要手动控制格式。C++的输入输出可以自动识别变量类型。
  5. 实际上cout和cin分别是ostream和istream类型的对象,>>和<<也涉及运算符重载等知识,这些知识我们我们后续才会学习,所以我们这里只是简单学习他们的使用。

注意:早期标准库将所有功能在全局域中实现,声明在.h后缀的头文件中,使用时只需包含对应头文件即可,后来将其实现在std命名空间下,为了和C头文件区分,也为了正确使用命名空间,规定C++头文件不带.h;旧编译器(vc 6.0)中还支持<iostream.h>格式,后续编译器已不支持,因此推荐使用iostream+std的方式。

#include <iostream>
using namespace std;
int main()
{
	int a;
	double b;
	char c;

	// 可以自动识别变量的类型
	//输入
	cin >> a;
	cin >> b >> c;

	//输出
	cout << a << endl;
	cout << b << " " << c << endl;
	return 0;
}

简单来说C++中的cin和cout对标C中的scanf和printf。

ps: 关于cout和cin还有很多更复杂的用法,比如控制浮点数输出精度,控制整形输出进制格式等等。因为C++兼容C语言的用法,这些又用得不是很多,我们这里就不展开学习了。

std命名空间的使用惯例:

std是C++标准库的命名空间,如何展开std使用更合理呢?

  1. 在日常练习中,建议直接using namespace std即可,这样就很方便。
  2. using namespace std展开,标准库就全部暴露出来了,如果我们定义跟库重名的类型/对象/函数,就存在冲突问题。该问题在日常练习中很少出现,但是项目开发中代码较多、规模大,就很容易出现。所以建议在项目开发中使用,像std::cout这样使用时指定命名空间 + using std::cout展开常用的库对象/类型等方式。

4. 缺省参数

4.1 缺省参数概念

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

例如:

#include <iostream>
using namespace std;

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

参数的默认值即 a = 0

4.2 缺省参数分类

  • 全缺省参数
void Func(int a = 10, int b = 20, int c = 30)
{
    cout << "a = " << a << endl;
    cout << "b = " << b << endl;
    cout << "c = " << c << endl << endl;
}

int main()
{
    Func();
    Func(1);
    Func(1,2);
    Func(1,2,3);

    return 0;
}

打印结果:
在这里插入图片描述

  • 半缺省参数

半缺省参数所指的不是有一半的缺省值,而是一部分缺省值。

还需注意以下几点:

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

下面给出例子:

void Func(int a, int b = 20, int c = 30)
{
    cout << "a = " << a << endl;
    cout << "b = " << b << endl;
    cout << "c = " << c << endl << endl;
}

int main()
{
    //Func();
    Func(1);
    Func(1,2);
    Func(1,2,3);

    return 0;
}

打印结果:

在这里插入图片描述

5. 函数重载

5.1 函数重载的概念

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

  • 参数类型不同
int Add(int left, int right)
{
	cout << "int Add(int left, int right)" << endl;
	return left + right;
}
double Add(double left, double right)
{
	cout << "double Add(double left, double right)" << endl;
	return left + right;
}
  • 参数个数不同
void f()
{
	cout << "f()" << endl;
}

void f(int a)
{
	cout << "f(int a)" << endl;
}
  • 参数类型顺序不同
void f(int a, char b)
{
	cout << "f(int a,char b)" << endl;
}

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

int main()
{
	f(1, 'x');
	f('x', 1);
	
	return 0;
}

ps: 系统会根据它们的参数类型自动匹配最相符的函数进行调用,即使函数名相同也是可以的。

5.2 C++支持函数重载的原理–名字修饰(name Mangling)

在C++中,函数重载的实现依靠“名字修饰”(name mangling),这是编译器用来区分不同函数的一种方式。名字修饰是编译器内部的行为,它将函数的名字和参数类型转换为一个内部可识别的形式。这确保了即使在不同的编程语言中,函数的名字可以是唯一的,避免了名称冲突。

例如,在C++中,以下两个函数可以同时存在于同一个程序中,因为它们的名字在编译后分别被修饰成了不同的形式:

// 函数声明
int func(int);
float func(float);

在C/C++中,一个程序要运行起来,需要经历以下几个阶段:预处理、编译、汇编、链接。在vs2019中,当编译遇到到上面两个同名函数时,会在链接阶段处理这个问题,链接过程中编译器会找到两个函数的函数名,如下图,所以编译器才能准确的辨别两个同名函数。

在这里插入图片描述
而在C语言中,对于内部的函数名修饰是一样,所以编译器是无法区别的。 通过这里就理解了C语言为什么没办法支持重载了,因为同名函数没办法区分。而C++是通过函数修饰规则来区分,只要参数不同,修饰出来的名字就不一样,就支持了重载。

ps:如果两个函数函数名和参数是一样的,返回值不同是不构成重载的,因为调用时编译器没办法区分。

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值