C++系列
文章目录
- C++系列
- 前言
- 一、命名空间
- 二、缺省参数
- 2.1、缺省参数概念
- 2.2、 缺省参数分类
- 2.2.1、全缺省参数
- 2.2.2、半缺省参数
- 2.3、缺省参数的特点
- 三、函数重载
- 3.1、函数重载概念
- 3.2、构成函数重载的条件
- 3.2.1、参数类型不同
- 3.2.2、参数个数不同
- 3.2.3、参数类型顺序不同
前言
在学习C++之前,首先我们要知道—C++是在C的基础之上,容纳进去了面向对象编程思想,并增加了许多有用的库,以及编程范式等。这篇文章可以帮助我们了解c++是如何:
- 补充C语言语法的不足,以及C++是如何对C语言设计不合理的地方进行优化的。
- 为后续类和对象学习打基础。
一、命名空间
随着c语言的不断发展和完善,C语言库函数和关键字的定义,越来越多,这些变量、函数和类的名称将都存在于全局作用域中,而在我们编写程序时定义的函数、变量有时就会和库中所定义的发生冲突,如:
#include <stdio.h>
#include <stdlib.h>
int rand = 10;
// C语言没办法解决类似这样的命名冲突问题,所以C++提出了namespace来解决
int main()
{
printf("%d\n", rand);
return 0;
}
注:这里的报错就是因为在库中有一个rand()函数,与我们定义的rand变量名字冲突了。
C语言没有办法很好的解决这类问题,c++便提供了命名空间的方法,命名空间的目的是对标识符的名称进行本地化,以避免命名冲突或名字污染,namespace关键字的出现就是针对这种问题的。
命名空间定义:
定义命名空间,需要使用到namespace关键字,后面跟命名空间的名字,然后接一对{}即可,{}中即为命名空间的成员,如:
namespace ltn
{
// 命名空间中可以定义变量/函数/类型
int rand = 10;
int Add(int left, int right)
{
return left + right;
}
}
注意:一个命名空间就定义了一个新的作用域,命名空间中的所有内容都局限于该命名空间中
现在命名冲突的问题我们解决了,但是当你尝试对类中的函数进行调用时又会出现问题,如:
namespace ltn
{
int rand = 10;
int Add(int left, int right)
{
return left+right;
}
}
int main()
{
Add(1, 1);
return 0;
}
这是因为对于这个命名空间中所定义函数、变量等,我们是不可以直接访问的,需要配合“::”域作用符,指定域来进行访问,如:
namespace ltn
{
int rand = 10;
int Add(int left, int right)
{
return left+right;
}
}
int main()
{
printf("%d\n", ltn::rand);
ltn::Add(1, 1);
return 0;
}
如果我们不指定域,编译器首先会去局部查找,其次会去全局域查找,并不会去我们所定义的命名空间中查找,这一点会在后面验证。
在我们编写c++代码时,往往会在代码中,编写这样一段代码“using namespace std;”这里的std就是我们标准库所在的域,而这句代码的意思就是,将这个命名空间展开(权限放开),使我们在使用库中定义的函数、关键字时,不在受域限制,我们可以通过自己定义的命名空间来验证这里的问题,如:
在不指定命名空间时程序是无法编译的,接下来我们展开ltn这个命名空间:
#include <stdio.h>
#include <stdlib.h>
namespace ltn
{
int rand = 0;
int Add(int left, int right)
{
return left + right;
}
}
int main()
{
Add(1, 1);
return 0;
}
对上面个这中情况,我们如果展开命名空间,rand变量就会和库中的rand()函数冲突,如果不展开每次都要指定域访问,又有点麻烦,这时我们就可以将
命名空间中我们经常使用的函数、变量具体引,如:
还以一点,当我们在两个不同的文件中,定义了相同的命名空间他们是会自动合并的,例:
namespace ltn
{
int add(int x,int y)
{
printf("add\n");
return 0;
}
}
在test.h文件中定义一个和test.c相同的命名空间,这是我们只需要将test.c中的命名空间展开test.h命名空间中的add函数一样可以使用。
二、缺省参数
2.1、缺省参数概念
缺省参数是声明或定义函数时为函数的参数指定一个缺省值。在调用该函数时,如果没有指定实参,则采用该形参的缺省值,否则使用指定的实参。
void Func(int a = 0)
{
cout<<a<<endl;
}
int main()
{
Func(); // 没有传参时,使用参数的默认值
Func(10); // 传参时,使用指定的实参
return 0;
}
2.2、 缺省参数分类
2.2.1、全缺省参数
void Func(int a = 10, int b = 20, int c = 30)
{
cout << "a = " << a << endl;
cout << "b = " << b << endl;
cout << "c = " << c << endl;
}
int main()
{
Func();
cout <<"-----------------" << endl;
Func(1);
cout << "-----------------" << endl;
Func(1,2);
cout << "-----------------" << endl;
Func(1,2,3);
return 0;
}
但我们使用全缺省时,我们可以选择性给函数传递数据。
2.2.2、半缺省参数
void Func(int a, int b = 10, int c = 20)
{
cout << "a = " << a << endl;
cout << "b = " << b << endl;
cout << "c = " << c << endl;
}
int main()
{
Func(1);
cout << "-----------------" << endl;
Func(1,2);
cout << "-----------------" << endl;
Func(1,2,3);
return 0;
}
半缺省函数需要注意的是:
- 半缺省参数必须从右往左依次缺省,不能间隔着给
- 半缺省参数在调用是,我们传递的参数是从左到右依次匹配的
2.3、缺省参数的特点
1、缺省参数不能在函数声明和定义中同时出现:
语法规定,当我们对函数进项声明和定义分离时,缺省参数不可同时存在,如果同时存在,而两个位置提供的值不同,那编译器就无法确定到底该用哪个缺省值。
2、 缺省值必须是常量或者全局变量
这个大家自己验证吧。
三、函数重载
3.1、函数重载概念
函数重载:是函数的一种特殊情况,C++允许在同一作用域中声明几个功能类似的同名函数,这些同名函数的形参列表(参数个数 或 类型 或 类型顺序)不同,常用来处理实现功能类似数据类型不同的问题
3.2、构成函数重载的条件
构成重载的函数在调用时编译器会根据我们传递的参数,匹配调用合适的函数。
3.2.1、参数类型不同
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;
}
int main()
{
Add(1,1);
Add(1.1, 1.2);
return 0;
}
程序执行时,编译器自动匹配合适的函数进行调用。
3.2.2、参数个数不同
void f()
{
cout << "f()" << endl;
}
void f(int a)
{
cout << "f(int a)" << endl;
}
int main()
{
f();
f(1);
return 0;
}
这里要注意的是,我们上面提到的缺省参数如果像下面这样使用,会造成二义性的问题:
3.2.3、参数类型顺序不同
需要注意的是,这里说的参数类型顺序不同指的是不同类型的参数。
void f(int a, char b)
{
cout << "f(int a,char b)" << endl;
}
void f(char b, int a)
{
cout << "f(char b, int a)" << endl;
}
int main()
{
f(10, 'a');
f('a', 10);
return 0;
}
至于c++是如何支持函数重载的,大家感兴趣可以搜一下c++中函数名命名规则。