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的主要内容,如果未能解决你的问题,请参考以下文章
从0带你入门C++,本文3万字含C++全套基础语法和练习套题,肝!