前几天开始学习C++语言,看到了函数重载的问题,就总结一下
什么是C++呢?(以下一段话出自搜狗百科),C++是一种面向对象的计算机程序设计语言,由美国AT&T贝尔实验室的本贾尼·斯特劳斯特卢普博士在20世纪80年代初期发明并实现(最初这种语言被称作“C with Classes”带类的C)。它是一种静态数据类型检查的、支持多重编程范式的通用程序设计语言。它支持过程化程序设计、数据抽象、面向对象程序设计、泛型程序设计等多种程序设计风格。
C++是C语言的继承,进一步扩充和完善了C语言,成为一种面向对象的程序设计语言。
那么什么是函数重载呢?
函数重载是指在同一作用域内,可以有一组具有相同函数名,不同参数列表的函数,这组函数被称为重载函数。
注意,在C语言中,函数名是不允许相同的,如果函数名相同就会出现函数重载问题
例如:
int func(int a, int b);
int func(int a, char c);
int func(char a, char b);
上面几个函数的名字是一样的,在C语言中,这样是不被允许的,但是在C++中,函数名是可以相同的,但是函数的参数也必须不相同。
在C++中,如果两个函数名字相同并且在相同的域中被声明,但是参数表不同,则它们就是重载函数
int ADD(int a, int b);
int ADD(float a, float b);
在C++中,这两个函数就是重载函数,重载函数的规则如下:
1.函数名称必须相同
2.参数列表必须不同
3.函数的返回类型可以相同也可以不相同。
注意,参数列表不同包括参数的个数不同、类型不同或顺序不同这三种情况。
那么为什么C++中会允许函数重载呢?
因为C++代码在编译时会根据参数列表对函数进行重命名
例如ADD(int a, int b)这个函数,会被重命名为ADD3_int_int,当函数调用时,编译器会根据传入的实参去逐个匹配,以选择对应的函数,如果匹配失败,编译器就会报错,这叫做重载决议(Overload Resolution)。
不同的编译器有不同的重命名方式,这例仅仅是举个栗子,并不一定是这种命名方式,如果你想具体知道编译器是如何实现的,可以在百度词条上看,或者找个编译器自己试试。
函数的缺省参数问题又是什么呢?
缺省参数,看字面意思,好像是函数可以在调用的时候缺省参数?
其实就是这样,函数在声明的时候制定初始值,在调用时就可以省略那个参数,但是函数的缺省参数还有许多规则:
1.函数能从后面一个参数开始省略,如果你想省略一个参数,那么你必须省略它后面的所有参数,即带缺省值的参数必须放在参数表的最后面
//正确
int Compare(int a, int b = 1);
//错误,一旦为函数的某个参数指定了缺省值,则必须为后续参数也定义缺省值
int RemoveNode1(LinkNode* head, int a = 1, int b);
//正确
int RemoveNode2(LinkNode* head, int a = 1, int b = 2, int c = 3);
2.缺省值必须是常量,所以缺省参数必须通过值参或常参传递
3.如果函数已经带有缺省参数的函数原型声明,则在该函数的定义中不允许出现缺省值。
4.调用函数时,如果略去一个参数传递,则略去后续所有参数传递
RemoveNode(head, 2);
RemoveNode(head, 2, 3);
//错误
RemoveNode(head, 2, , 4);
注意,要慎用函数的缺省参数,滥用的话会损害代码的结构和可读性,而且在函数重载时可能会出现二义性,例如:
void func(int a);
void func(int a, int b = 1);
//按照下面调用的话就会出现错误
func(100);
命名空间
在C++中,名称(name)可以是符号常量、变量、宏、函数、结构、枚举、类和对象等等。
为了避免,在大规模程序的设计中,以及在程序员使用各种各样的C++库时,这些标识符的命名发生冲突,标准C++引入了关键字namespace(命名空间/名字空间/名称空间/名域),可以更好地控制标识符的作用域。
namespace s1
{
int a = 1;
}
namespace s2
{
int a = 2;
}
就像上面的代码,在不同的命名空间有同一个名字的变量a,调用如下:
int c = s1::a;
int d = s2::a;
注意:这个符号(::) 是作用域解析运算符,用这个来访问命名空间内的成员
命名空间中的成员可以分为内部成员和外部成员,例如:
namespace s1
{
int a = 1;
namespace s2
{
int b = 2;
void fun()
{b++;}
}
//命名空间s2内的fun函数
void fun(){a++;}
//错误不能在命名空间中声明子命名空间
namspace s2;
}
//命名空间s1的fun函数的外部定义
void s1::fun(){a++;}
//命名空间s2的fun函数的外部定义
void s1::s2::fun(){b++;}
不能直接使用“命名空间名::成员名 ……”定义方式,为命名空间添加新成员,而必须先在命名空间的定义中添加新成员的声明.
命名空间是开放的,可以多次声明和定义同一命名空间,可以用这样的方式来添加新成员
namespace s
{
int a;
int arr[];
}
namspace a
{
int c;
char* str;
}
//现在命名空间a内有元素a,c,arr,str四个成员
为了省去每次调用Inner成员和标准库的函数和对象时,都要添加Outer::Inner::和sta::的麻烦,可以使用标准C++的using编译指令来简化对命名空间中的名称的使用。格式为:
using namespace 命名空间名[::命名空间名……];
在这条语句之后,就可以直接使用该命名空间中的标识符,而不必写前面的命名空间定位部分。因为using指令,使所指定的整个命名空间中的所有成员都直接可用。
例如:
#include<iostream>
//例如下面的代码
using namespace std;
简单的总结一下这三个东西,以后在学习C++中继续深入的了解和使用吧