C/C++教程

c++从零开始---函数重载

本文主要是介绍c++从零开始---函数重载,对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!

1、函数重载的概念

使用函数重载创建函数使得用户能够使用多个同名的函数,他们完成不同的工作,使用不同的参数列表,但是函数名相同。
重载函数就像是有多种含义的动词。重载函数的关键是函数的参数列表—也称为函数特征标。如果两个函数的参数的数目和类型相同,同时参数的排列顺序也相同,则它们的特征标相同,而变量名是无关紧要的。例如,可以定义一组原型如下的 print() 函数:

void print(const char *str, int width); // #1
void print(double d, int width); // #2
void print(long l, int width);// #3
void print(int i, int width); // #4
void print(const char* str); // #5

而使用 print() 函数时,编译器将根据所采取的用法使用有相应特征标的原型:

print("Pancakes", 15); // use #1
print("Syrup");        // use #5
print(1999.0, 10);     // use #2
print(1999, 12);  	   // use #4
print(1999L, 15);      // use #3 

当输入的参数类型和任意一个重载函数都不匹配时,c++ 将试图使用标准类型转换强制进行匹配。例如:

unsigned int year = 2000;
print(year, 5);

因为重载函数 print() 没有第一个参数是 unsinged 类型的,因此 c++ 尝试进行类型强制转换。如果 print() 函数只有 #2 (没有 #3 和 #4)类型,那么将直接使用 #2。但是 print() 的 #2、3、4 的第一个参数都是数字,这样 c++ 不能强制转换,将拒绝执行代码。

2、注意事项

  1. 编译器在检查函数特征标时,将把类型引用和类型本身视为同一个特征标:
double cube(double x);
double cube(double &x);

当输入参数 x,与这两个原型都相互匹配。

  1. 匹配函数时,要区分 const 和非 const 变量:
void dribble(char * bits);
void dribble(const char *cbits);
void drip(char* bits);

const char p1[10] = "wang";
char p2[10] = "wang";
dribble(p1);
dribble(p2);
drip(p1); no match

注意到 dribble() 函数可以输入 const 和非 const 参数,但是 drip() 不能输入 const 参数。因为不能将 const 值赋给非 const 值。

  1. 特征标是函数重载的关键,而非函数类型:
long gronk(int n, float m);
double gronk(int n,float m);

以上两个函数时互斥的,它们并非重载函数,但是函数名相同,c++ 将不知道如何使用。

3、重载引用参数

类设计和 STL 经常使用引用参数,因此知道不同引用类型的重载很重要,请看以下三个原型:

void sink(double & r1); // 与可修改的左值参数匹配
void sank(const double & r2); // 与可修改的左值参数、const 左值参数和右值参数匹配
void sunk(double && r3); // 与右值匹配

注意到与 r1 和 r3 匹配的参数都与 r2 匹配。如果重载使用这三种参数的函数,结果如何?答案是将调用最匹配的版本:

void stove(double & r1);
void stove(const double &r2);
void stove(double && r3);

double x = 55.5;
const double y = 32.0;
stove(x); // calls stove(double &)
stove(y); // calls stove(const double &)
stove(x+y); // calls stove(double&&)

以上程序中,如果没有定义函数 stove(double &&), stove(x+y) 将调用 stove(const double &)。

4、何时使用重载

应当秉持一个原则:仅当函数基本上执行相同的任务,但使用不同形式的数据时,才使用函数重载。


补充内容—左值与右值(详参考此处)

1、左值和右值的概念
C++中左值(lvalue)和右值(rvalue)是比较基础的概念,虽然平常几乎用不到,但C++11之后变得十分重要,它是理解 move/forward 等新语义的基础。
左值与右值这两个概念是从 C 中传承而来的,左值指既能够出现在等号左边,也能出现在等号右边的变量;右值则是只能出现在等号右边的变量。

int a; // a 为左值
a = 3; // 3 为右值

左值是可寻址的变量,有持久性;
右值一般是不可寻址的常量,或在表达式求值过程中创建的无名临时对象,短暂性的。
左值和右值主要的区别之一是左值可以被修改,而右值不能。
2、左值引用和右值引用
左值引用:引用一个对象;
右值引用:就是必须绑定到右值的引用,C++11中右值引用可以实现“移动语义”,通过 && 获得右值引用。

int x = 6; // x是左值,6是右值
int &y = x; // 左值引用,y引用x
int &z1 = x * 6; // 错误,x*6是一个右值
const int &z2 =  x * 6; // 正确,可以将一个const引用绑定到一个右值
int &&z3 = x * 6; // 正确,右值引用
int &&z4 = x; // 错误,x是一个左值

右值引用和相关的移动语义是C++11标准中引入的最强大的特性之一,通过std::move()可以避免无谓的复制,提高程序性能。


这篇关于c++从零开始---函数重载的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!