C/C++基础复习(六)函数

C/C++ 2014年07月04日 ,

经过对C/C++语句的复习后,继续对函数进行温习。http://furzoom.com/

函数

函数的定义

函数由函数名以及一组操作数类型唯一的表示。函数的操作数(形参),在一对圆括号中声明,形参与形参之前以逗号分隔。函数执行的运算在一个称为函数体的块语句中定义。每一个函数都有一个相关联的返回类型

C++语言使用调用操作符(即一对圆括号)实现函数的调用。调用操作符的操作数是函数名和一组由逗号分隔的实参

函数体是一个作用域,在函数体内定义的变量称为局部变量

函数形参在函数的形参列表中定义,并由调用函数时传递的实参进行初始化。

函数的返回类型可以是内置类型、类类型或复合类型,还可以是void类型,表示不返回任何值。函数不能返回另一个函数或者内置数组类型,但是可以返回指向函数的指针,或指向数组元素的指针的指针。

函数定义时必须指定函数的返回类型。

函数形参表可以为空,但不能省略。

参数传递

每次调用函数时,都会重新创建该函数所有的形参,此时所传递的实参将会初始化对应的形参。形参的初始化与变量的初始化一样,如果形参具有非引用类型,则复制实参的值,如果形参为引用类型,则它只是实参的别名。

函数的形参可以是指针,此时将复制实参指针。

函数的参数如果是vector或其他标准库容器类型形参,调用含有普通的非引用vector形参的函数将复制容器的每一个元素,造成较大的开销。从避免复制窗口的角度出发,就考虑将形参声明为引用类型。事实上,C++更倾向于通过传递指向容器中需要处理元素的迭代器来传递容器。

void print(vector<int>::const_iterator beg,
           vector<int>::const_iterator end)
{
    while(beg != end)
    {
        cout<<*beg++;
        if(beg != end)
            cout<<" ";    // no space after last element
    }
}

数组有两个特殊的性质,影响使用在数组上的函数:

  1. 不能复制数组。
  2. 使用数组名时,数组名会自动转化为指向其第一个元素的指针。

形参数组可以按照如下三种方式进行声明函数,以int型数组为例,

// three equivalent definitions of printValues
void printValues(int *);
void printValues(int[]);
void printValues(int[10]);

三种类型的形参都等价于int*类型。编译会忽略形参中的数组长度,因此数组作为形参时不写数组的长度。建议声明为指针的方式。

当函数的参数声明为数组的引用时,需声明数组的长度,编译将会进行相应的检查。如,

// ok: parameter is a reference to an array; size of array is fixed
void printValues(int (&arr)[10]){}
int main()
{
    int i = 0, j[2] = {1,2};
    int k[10] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
    printValues(&i);// error: argument is not an array of 10 ints
    printValues(j); // error: argument is not an array of 10 ints
    printValues(k); // ok: argument is an array of 10 ints
    return 0;
}

可以采用如下的三种方法之一来确保对数组的操作是在边界内:

  1. 数组本身放置一个标记来检测数组的结束。如C字符串的处理。
  2. 传递给数组第一元素和最后一个元素的下一个位置的指针。
  3. 显式地传递数组大小的参数。

在C++中含有可变参数的函数,其可变部分只能进行简单类型参数传递,由于没有声明参数类型,将不会进行类型的检查。

return语句

return语句用于结束当前正在执行的函数,并将控制权返回给调用此函数的函数。

return;
return expression;

不带返回值的return语句只能用于返回类型为void的函数。在返回值为void的函数中,return返回语句不是必需的。

不能返回局部变量的引用,也不能返回局部变量的指针

返回引用的函数,返回的是一个左值。如,

char &get_val(string &str, string::size_type ix)
{
    return str[ix];
}
int main()
{
    string s("furzoom");
    get_val(s,1) = 'U';    // change s[1] to U, s is "fUrzoom"
    return 0;
}

直接或间接调用自己的函数称为递归函数

函数声明

与变量必须先声明后使用一样,函数也必须在被调用之前先声明,可以声明多次,但只能定义一次。

C++函数声明支持使用默认参数。在同一个文件中默认参数只能指定一次,可在定义中也可以在声明中。为了达到默认参数的使用意义,一般将在头文件中指定。

局部对象

只有当定义它的函数被调用时才存在的对象称为自动对象。自动对象在每次调用函数时创建和撤销。

静态局部对象是位置函数作用域内,但生命周期跨越了这个函数的多次调用。使用static进行声明。

内联对象

一些简短的函数,如求最大值,其只有一个表达式,有如下好处:

  1. 1.阅读和理解函数max()的调用,要比读一条用等价的条件表达式取代函数调用表达式并解释它的含义要容易的多。
  2. 2.如果需要做任何修改,修改函数要比找出并修改每一处等价表达式容易的多。
  3. 3.使用函数可以确保统一的行为,每个测试都保证以相同的方式实现。
  4. 4.函数可以重用,不必为其他应用重写代码。

但其有潜在的缺点:函数的调用比求解等价表达式要慢得多。

inline函数就是将调用它的时进行内联地展开,避免函数调用的开销。inline说明对于编译器来说只是一个建议,编译器可以选择忽略这个。

inline函数应该在头文件中定义,这一点不同于其他函数。

类的成员函数

类的成员函数就是在类中定义的函数,与普通函数相同。但其函数原型必须在类中定义。

每一个成员函数都有一个额外的、隐含的形参this。形参this初始化为调用函数的对象的地址。

常量成员函数在定义时在其最后面使用const声明。该函数不能修改成员变量。const对象、指向const对象的指针或引用只能用于调用其const成员函数,如果尝试调用非const成员函数,则是错误的。

构造函数是特殊的成员函数,构造函数与类同名,且没有返回值,其他与普通函数相同。如果没有为一个类显式的定义构造函数,编译器底土自动为这个类生成默认构造函数,通常称为默认构造函数

通常将类的声明放置在头文件中,在类外定义的成员函数则放在源文件中。

重载函数

出现在相同作用域中的两个函数,如果具有相同的名字而形参不同,则称为重载函数

任何程序都仅有一个main函数的实例,main函数不能重载。

如果两个函数声明的返回值类型和形参表完全匹配,则将第二个函数声明视为第一个的重复声明。如果两个函数的形参表完全相同,但返回类型不同,则第二个声明是错误的。

函数重载时,就避免二义性。如,

void print(int a){}
void print(int a, int b = 0){}
print(1);     // error: ambiguous

在函数重载,确定最佳匹配时,按以下方式降序进行:

  1. 1.精确匹配。实参与形参类型相同。
  2. 2.通过类型提升实现匹配。
  3. 3.通过标准转换实现匹配。
  4. 4.通过类类型转换实现匹配。

如,

void print(int){}
void print(short){}
print('a');     // char promotes to int, so matched print(int)

指向函数的指针

函数指针是指指向函数而非指向对象的指针。

通常使用typedef来简化函数指针的声明。

函数指针初始化时需使用形参及返回值都相同的函数进行初始化。

指向重载函数的指针必须明确其指向的函数。

Terms

ambiguous call

arguments

automatic objects

best match

call operator

candidate functions

const member function

constructor

constructor initializer list

default constructor

function

function body

function matching

function prototype

inline function

local static objects

local variables

object lifetime

overload resolution

overloaded function

prarmeters

recursive function

return type

synthesized default constructor

temporary object

this pointer

viable functions

如无特别说明,本站文章皆为原创,若要转载,务必请注明以下原文信息:
日志标题:《C/C++基础复习(六)函数》
日志链接:http://furzoom.com/c-cplusplus-primetive-knowledge-6/
博客名称:枫竹梦

【上一篇】
【下一篇】

发表评论

插入图片

NOTICE1:请申请gravatar头像,没有头像的评论可能不会被回复!

回到顶部