C++基础语法1

Posted 山舟

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了C++基础语法1相关的知识,希望对你有一定的参考价值。


前言

前面写了C语言和数据结构的部分内容,从本篇文章开始正视进入C++相关的内容。


提示:以下是本篇文章正文内容。

一、C++关键字(C++98)

下图是C++98中规定的63个关键字。

在这里插入图片描述

可以看到,其中有不少关键字是C语言中常用的,这也一定程度上说明了C++兼容C语言的语法


二、C++的第一个程序

在学习C语言时,第一段代码是打印"hello world"到控制台,下面用C++实现。

代码如下(示例):

#include <iostream>//C++中的头文件与为了C的头文件相区分不加.h
using namespace std;

int main()
{
	cout << "hello world" << endl;
	return 0;
}

读到这里,可能你会有疑问:namespace,std是什么?cout和endl是什么?

不必着急,请看下文。


二、命名空间

1.命名冲突问题

在C/C++中,变量、函数和后面要学到的类都是大量存在的,这些变量、函数和类的名称如果不加处理将都存在于同一作用域中,可能会导致很多冲突

使用命名空间namespace的目的是对标识符的名称进行本地化,以避免命名冲突,namespace关键字的出现就是针对这种问题的。

如下面的代码

代码如下(示例):

//C语言
int main()
{
	int scanf = 10;
	scanf("%d", &scanf);
	return 0;
}

C语言中变量命名不允许与关键字相同,而scanf是一个库函数的名称,所以从语法的角度来说第三行的代码没问题。

但第四行由于C语言遵循就近原则,即将前后两个scanf都当做值为10的整型变量,而不是将前一个scanf识别为库函数。

如果将scanf定义在全局而不是main函数内,则编译时会直接报错重定义。
在这里插入图片描述

上面的情况发生了命名冲突,使用C语言解决不了这个问题,只能建议不要这样命名; 而C++里可以使用命名空间来解决这个问题。


2.命名空间的定义

定义命名空间,需要使用到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;
	}

	//n2中嵌套了n3
	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;
	}
}

3.命名空间的使用

使用命名空间解决上面冲突的代码的问题。

代码如下(示例):

namespace yh
{
	int scanf;
	int strlen;
}
int main()
{
	//下面的语句编译出错
	//因为编译器并不能区分这里的scanf和strlen哪个是全局域里的,哪个是命名空间yh里的
	scanf("%d", &scanf);
	scanf("%d", &strlen);
	printf("%d\\n", scanf);
	printf("%d\\n", strlen);
	return 0;
}

那么定义了命名空间,如何使用呢?有如下三种方法。

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

这就是在告诉编译器,某一变量是某一命名空间内的变量。

代码如下(示例):

namespace yh
{
	int scanf;
	int strlen;
}
int main()
{
	//加命名空间名称及作用域限定符::
	//指定scanf和strlen是yh命名空间内的变量,如果命名空间内有函数,使用方法同理
	scanf("%d", &yh::scanf);
	scanf("%d", &yh::strlen);
	printf("%d\\n", yh::scanf);
	printf("%d\\n", yh::strlen);
	return 0;
}

(2)使用using将命名空间中成员引入

就是将命名空间中的一个或几个成员引入,在之后访问这几个被引入的成员时不必在其前面加域作用限定符。

代码如下(示例):

namespace n
{
	int a = 10;
	int b = 20;
}
using yh a;
using yh b;
int main()
{
	printf("%d %d\\n", a, b);
	return 0;
}

(3)使用using namespace将命名空间整体引入

就是将某个命名空间全部引入,访问该命名空间的任何成员均不必在其前面加域作用限定符。

代码如下(示例):

namespace n
{
	int a = 10;
	int b = 20;
}
using namespace n;
int main()
{
	printf("%d %d\\n", a, b);
	return 0;
}

namespace已经解决了,返回最开始的问题:std是什么?

C++库为了防止命名冲突,把标准库内部的东西(如cout,endl等等)均定义在一个名为std的命名空间中。要使用标准库中的东西,也需要使用上面的三种方法的其中一种。

(1)在每个使用的地方均指定,是最麻烦也是最规范的方式。如下。

std::cout <<"hello world" << std::endl;

(2)对部分常用的进行展开,在之后使用这些时就不需要再指定了。

using std cout;
using std endl;

(3)使用using namespace std把std整个展开,相当与std内部的东西全部进入全局域。但可能与自己定义的变量冲突,所以规范的工程项目中不推荐这种方式,日常练习中可以使用。


三、C++的输入和输出

C++中的输入函数cin和输出函数cout函数在头文件iostream中。

代码如下(示例):

int main()
{
	int a;
	cin >> a;//从控制台输入一个值流向a
	cout << a;//将a的值流向控制台,即输出到控制台
	cout << endl;//endl是换行符
	return 0;
}

那么C++中新的输入输出方式对比C语言的scanf和printf有什么优势呢?

cin和cout不需要用%d,%f……指定变量的类型,可以自动识别变量类型。
在这里插入图片描述
cin和scanf一样遇到空格或者换行会停止读取,cin在读入数据是变量不需要加取地址符&。


四、缺省参数

1.概念

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

缺省参数可以使函数在调用时更加灵活。

代码如下(示例):

void test1(int a = 10)
{
	cout << a << endl;
}

int main()
{
	test1();//不传参,使用默认值10
	test1(50);//传参,使用实参50
	return 0;
}

运行结果如下:

在这里插入图片描述


2.缺省参数分类

(1)全缺省:所有的参数都给出了默认值

代码如下(示例):

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

int main()
{
	//可以传不同个数的实参
	test2();
	test2(1);
	test2(1, 2);
	test2(1, 2, 3);
	return 0;
}

运行结果如下:

在这里插入图片描述


(2)半缺省:部分参数给出默认值

要求给出默认值的参数从右向左连续

代码如下(示例):

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

int main()
{
	//test3();//a的值不确定,不合法

	//函数中a的值必须给出,所以至少需要传一个参数
	test3(1);
	test3(1, 2);
	test3(1, 2, 3);
	return 0;
}

运行结果如下

在这里插入图片描述


注意:

(1)半缺省参数的默认值必须从右往左依次给出,不能有间隔。
(2) 缺省参数不能在函数声明和定义中同时出现。

//test.h
void TestFunc(int a = 10);

//test.c
void TestFunc(int a = 20)
{}

//声明与定义位置同时出现默认值,而两个位置提供的值又不同,那编译器就无法确定到底该用哪个缺省值。

五、函数重载

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

注意:返回值不同,缺省参数的默认值不同不构成重载。

代码如下(示例):

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()
{
	cout << Add(10, 20) << endl;
	cout << Add(10.1, 20.2) << endl;
	cout << Add(10L, 20L) << endl;//匹配long类型

	return 0;
}

一个小问题

代码如下(示例):

void f(int a, int b = 10)
{}

void f(int a)
{}

int main()
{
	f(1);
	return 0;
}

上面的两个f函数构成重载,但是在main函数中调用的时候编译器无法区分调用的是哪个f函数,所以实际情况中一定要避免写出这样的代码。


感谢阅读,如有错误请批评指正

以上是关于C++基础语法1的主要内容,如果未能解决你的问题,请参考以下文章

用于初始化数组的 c++ 语法

JSP开发中的基础语法

java学习总结--2.基础语法

从0带你入门C++,本文3万字含C++全套基础语法和练习套题,肝!

C++三大特性之继承,由浅入深全面讲解,由基础语法到深度刨析。

C++三大特性之继承,由浅入深全面讲解,由基础语法到深度刨析。