《C++primerplus》第7章:函数——C++的编程模块-创新互联

复习函数的基本知识

C++对于返回值的类型有一定的限制:不能是数组,但可以是其他任何类型——整数、浮点数、指针,甚至可以是结构和对象(有趣的是,虽然C++函数不能直接返回数组,但可以将数组作为结构或对象组成部分来返回)。

塔什库尔干塔吉克ssl适用于网站、小程序/APP、API接口等需要进行数据传输应用场景,ssl证书未来市场广阔!成为创新互联的ssl证书销售渠道,可以享受市场价格4-6折优惠!如果有意向欢迎电话联系或者加微信:18980820575(备注:SSL证书合作)期待与您的合作!

在函数声明的参数列表中,可以包括变量名,也可以不包括。原型中的变量名相当于占位符,因此不必与函数定义中的变量名相同。

在C++中,括号为空与在括号中使用关键字 void 是等效的——意味着函数没有参数。

在 C++ 中,不指定参数列表时应使用省略号:如:
void say_bye(…);
通常,仅当与接受可变参数的 C 函数(如printf()) 交互时才需要这样做。

静态类型检查,编译阶段,检查函数参数类型是否正确,并进行可以进行的类型转换。

函数参数和按值传递

声明中的变量名不必与定义中的变量名相同,而且可以省略。

一句话总结,按值传递就是函数自身会创建以形参名为名的变量来使用,并不会修改给函数传值的实参的值。

函数和数组

函数如何用指针来处理数组?
在大多数情况下,C++ 将数组名视为指针,但有一些例外,首先,数组声明使用数组名来标记存储位置;其次,对数组名使用 sizeof 将得到整个数组的长度(以字节为单位),第三,将地址运算符&用于数组名时,将返回整个数组的地址,对它加1是加整个数组占用的字节数,而不是单个元素的字节数。

int sum_arr(int arr[], int n);

int sum_arr(int * arr, int n);

用 int * arr 替换了 int arr[],这两个函数头都是正确的,在C++中,仅在函数参数列表中,int *arr 和 int arr[]才是相同的。它们都意味着 arr 是一个int指针。然而,数组表示法( int arr[] ) 提醒用户,arr 不仅指向int,还指向int数组的第一个int。
当指针指向数组的第一个元素时,一般使用数组表示法;而当指针指向一个独立的值时,一般使用指针表示法。

但在其它上下文中,并不能用 int arr[]来声明一个指针。

传递常规变量时,函数将使用该变量的拷贝,但传递数组时,函数将使用原来的数组。实际上,这种区别并不违反C++按值传递的原则,传递数组时仍然传递了一个值,这个值是地址,这个值被赋给了一个新的变量,但是这个值(也就是这个地址)指向的就是原来的数组。

注意,函数参数里使用int arr[],在函数内对arr使用sizeof,得到的是指针变量的长度,而不是整个数组的长度。这也是必须显示传递数组长度,而不是在函数内部使用sizeof的原因;指针本身并没有指出数组的长度。

注意,为将数组类型和元素数量告诉数组处理函数,请通过两个不同的参数来传递它们:
void fillArray(int arr[], int size);
而不要试图使用方括号表示法来传递数组长度:
void fillArray(int arr[size]);这是错误的。

void show_array(const double ar[], int n);
const double arr[],表明,指针ar指向的是常量数据,这意味着不能使用arr修改该数据。但这并不意味着原始数组必须是常量,而只是意味着不能在show_array()函数中使用 ar 来修改这些数据。

对于处理数组的 C++ 函数,必须将数组中的数据种类、数组的起始位置和数组中元素数量提交给它;传统的C/C++方法是,将指向数组起始处的指针作为一个参数,将数组长度作为第二个参数。还有另一种给函数提供所需信息的方法,即指定元素区间(range),这可以通过传递两个指针来完成:一个指针标识数组的开头,另一个指针标识数组的尾部。

C++禁止将const变量的地址分配给非const指针。(如果非要这样做,可以使用强制类型转换来突破这种限制)

注意
const int * ps
int * const ps
两者的区别是,前者表示指针指向的内容不能被修改,后者表示指针本身不能被修改

函数和二维数组

int sum( int (*ar)[4], int size);
int sum( int ar[] [4], int size);

使用方式

ar[r][c];

*(*(ar+r)+c)

函数和C-风格字符串

C-风格字符串由一系列字符组成,以空字符结尾。有关函数的数组的规则也适用于字符串函数。但字符串还有一些特殊的规则。

假设要将字符串作为参数传递给函数,则表示字符串的方式有三种:

  • char数组;
  • 用括号引起的字符串常量(也称字符串字面值);
  • 被设置为字符串的地址的 char 指针
    但上述 3 种选择的类型都是 char 指针(准确地说是 char*),因此可以将其作为字符串处理函数的参数

可以说是将字符串作为参数来传递,但实际传递的是字符串第一个字符的地址。这意味着字符串函数声明将其表示字符串的形参声明为 char* 类型。

C-风格字符串与常规 char 数组之间的一个重要区别是,字符串有内置的结束字符,这意味着不必将字符串长度作为参数传递给函数,而函数可以使用循环以此检查字符串中的每个字符,指导遇到结尾的空字符为止。

一种处理字符串中字符的标准方式:

while(*str){statements;
	str++;
}
函数和结构

为结构编写函数比为数组编写函数要简单得多,虽然结构变量和数组一样,都已存储多个数据项,但在涉及到函数时,结构变量的行为更接近于基本的单值变量。使用结构来编程时,最直接的方式是像处理基本类型那样来处理结构:也就是说,将结构作为参数传递,并在需要时将结构用作返回值使用。

按值传递;传递地址,使用指针来访问结构的内容;按引用传递。

按值传递:当将一个实参传递给函数时,结构的内容会被拷贝到形参中,函数随后使用拷贝完成工作。

使用指针传递的时候可以把要修改的结构的地址作为一个参数,传递给函数。

函数和 string 对象

除了getline()外,程序一般像对待内置类型一样对待string对象。

函数和 array 对象

如果需要使用array类,要包含头文件array,而名称array位于名称空间std中。

std::arrayexpenses;

使用指针来操作array的时候要注意运算优先级的问题;
(*pa)[i]才能表示array的第i项;

递归

从函数体内调用函数本身的地方开始,调用者暂停运行,执行被调用者代码。

递归的方式可用于分而治之的策略。

函数指针

与数据项相似,函数也有地址。函数的地址是存储其机器语言代码的内存的开始地址。通常,这些地址对用户而言,既不重要,也没有什么用处,但对程序而言,却很有用。例如,可以编写将另一个函数的地址作为参数的函数。这样第一个函数将能够找到第二个函数,并运行它。与直接调用另一个函数相比,这种方法很笨拙,但它允许在不同的时间传递不同函数的地址,这意味着可以在不同的时间使用不同的函数。

函数指针的基础知识
  1. 获取函数地址
    使用函数名(后面不跟参数)即可。

  2. 声明函数指针
    double pam(int);
    double (*pf) (int);

    void estimate(int lines, double (*pf) (int));
    estimate(50, pam);
    显然,使用函数指针时,比较棘手的是编写原型,而传递地址则非常简单。

  3. 使用指针来调用函数
    double pam(int);
    double (*pf) (int);
    pf = pam;
    double x = pam(4);
    double y = (*pf)(5);
    实际上,C++ 也允许像使用函数名那样使用 pf:
    double y = pf(5);
    第一种格式较为复杂,但是给出了强有力的提示——代码正在使用函数指针。

注意这里和普通变量不同,对函数指针来说 使用(*pf) 和pf作为函数名都是可以的,两者是等价的,而普通变量的指针不是这样。

深入探讨函数指针

注意以指针为元素的数组,和指向数组的指针在表示上的区别,
[]的优先级比*高

函数指针可以在声明的时候初始化,方法是 声明时像赋值语句一样赋值(赋值的内容是函数名)

注意使用 auto

还可以使用 typedef 来简化

你是否还在寻找稳定的海外服务器提供商?创新互联www.cdcxhl.cn海外机房具备T级流量清洗系统配攻击溯源,准确流量调度确保服务器高可用性,企业级服务器适合批量采购,新人活动首月15元起,快前往官网查看详情吧


当前标题:《C++primerplus》第7章:函数——C++的编程模块-创新互联
文章链接:http://ybzwz.com/article/ccjepp.html