C++(12)--函数基础:按值传递、传递数组、函数指针

模块化编程--函数

  • 1. 函数基本知识
  • 2. 函数的参数
    • 2.1 按值传递机制(小议按引用传递)
    • 2.2 使用数组做函数参数(用户头文件,const的防改)
    • 2.3 使用二维数组作为函数的参数
    • 2.4 使用函数指针作为函数的参数
      • 2.4.1 函数指针的基本内容
      • 2.4.2 函数指针数组的声明
      • 2.4.3 auto
      • 2.4.4 使用typedef 定义函数指针类型

《老九学堂C++课程》《C++ primer》学习笔记。《老九学堂C++课程》详情请到B站搜索《老九零基础学编程C++入门》
-------------简单的事情重复做,重复的事情用心做,用心的事情坚持做(老九君)---------------

1. 函数基本知识

函数分类:

  1. 内置函数(STL,Boost C++)
  2. 自定义函数(focus on)

C++ Standard Library(C 标准函数,输入/输出,数值,诊断,通用工具,国际化,语言支持,STL(迭代器,算法, 容器))

Boost C++:可移植,开源的代码库

函数三要素:返回值类型,函数名,参数列表

return_type functionName(parametersList){//函数体
}

自定义函数的完整写法:函数原型+函数调用+函数定义

int sum(int, int); // 函数原型,描述函数到编译器的接口,提前告诉编译器一声。不需要写参数名,以分号结尾
int main(){// 函数调用int result = sum(5,3);
}
// 函数定义
int sum(int num1, int num2){// 函数实现的代码return num1 + num2
}

注意:
1.函数原型和函数定义的头部类似,函数原型以分号结尾
2.函数原型中的参数名称可以省略,只写参数类型
3. C++返回值类型不能是数组,但是可以是其他任何类型(可以将数组做为结构或者对象的组成部分返回)

dmeo: 计算长方体和圆柱体的体积

//1.定义两个函数,分别用来计算两种形状的体积
//2.在mian 函数中用户可以选择计算某个形状的体积
void calcCuboid();   // 计算长方体的体积
void calcCylinder(); // 计算圆柱体的体积int main(){int choice = -1;while(choice){cout << "1. 计算长方体体积" << endl;cout << "2. 计算圆柱体的体积" << endl;cout << "0. 退出" << endl;cin >> choice;switch(choice){case 1:calcCuboid();break;case 2:calcCylinder();break;}}cout << "感谢使用本软件,觉得好用点个赞呗!" << endl;return 0;
}void calcCuboid(){// 输出长宽高double len, width, height;cout << "请输入长宽高:" ;cin >> len >> width >> height;// 计算体积double v = len * width * height;cout << "长方体的体积为:" << v << endl;
}
void calcCylinder(){double radius, height;cout << "请输入半径和高:";cin >>  radius >> height;// 计算体积, pow 的头文件 cmathdouble pi = 4 * atan(1.0); // arctan(1.0) 为45度角的弧度表示,pi为其4倍数// double v = 3.14 * pow(radius, 2) * height;double v = pi * pow(radius, 2) * height;cout << "圆柱体的体积为:" << v << endl; 
}

2. 函数的参数

2.1 按值传递机制(小议按引用传递)

按值传递:给函数传递变量时,变量值不会直接传递给函数,而是先制作变量值的副本,原始变量被存在栈上,将这个副本传递给函数。

void change(int);
int main(){int num = 9;change(num);cout << "num = " << num << endl;return 0;
}
void change(int num){num++;
}
num = 9

如果传递的是引用,那么原变量的值将会改变(引用,传递的是地址,改变的是地址中的值)

void change(int&);
int main(){int num = 9;change(num);cout << "num = " << num << endl;return 0;
}
void change(int &num){// 传递了引用,地址num++;
}
num = 10

2.2 使用数组做函数参数(用户头文件,const的防改)

1.数组作为函数参数时,只传递数组的首地址,并不传递整个数组空间
2.当数组名为实参时,数组首地址指针被传递到函数中

使用函数升级《小公主养成记》-- 函数放在自己写的头文件中(.h结尾),在.cpp文件中include

头文件princess.h编写:

// 使用函数升级《小公主养成记》中基本属性的输入和排序功能
// 基本属性: 体力, 智力, 魅力, 道德, 气质
#include  <iostream>using namespace std;
// 函数定义
// 给一个数组
void input(int [], int);
void show(int [], int);
//自行完成删除和修改数组元素// 函数实现
void input(int values[], int len){//int values[] 这么定义形参,传递数组的时候传递的是数组的指针//传数组时只有指针,建议再传一个数组长度if(len > 5){cout << "数组长度只能是5以内,越界了" << endl;return;  // 退出返回值为void的函数}string valueNames[] = {"体力", "智力", "魅力", "道德", "气质"};for(int i=0; i < len; i++){cout << valueNames[i] << ":" ;cin >> values[i];}
}void show(int values[], int len){string valueNames[] = {"体力", "智力", "魅力", "道德", "气质"};for(int i = 0; i < len; i++){cout << valueNames[i] << ":" << values[i] << endl;}
}

.cpp中导入自己写的头文件

#include <iostream>
#include "princess.h"  // 自己写的头文件使用双引号就可以了
using namespace std;
int main(){int values[5];input(values, sizeof(values)/sizeof(int));show(values,5);return 0;
}

传递数组参数时,不希望改动数组中的元素,在定义可以使用const 关键字

void show(const int [], int);
int main(){int valueArray[] = {90, 56, 67, 89, 100};return 0;
}
void show(const int valueArray[], int len){for(int i = 0; i < len; i++){// cout << valueArray[i]++ << endl;  ❌,编译不给过,告诉你只读cout << valueArray[i]<< endl; }
}

2.3 使用二维数组作为函数的参数

void show_2d(double (*)[5],int);
int main(){double valueArray[3][5] ={{45.5, 46.6, 47.7},{12.2, 13.3, 14.4},{15.5, 16.6, 17.7}};show_2d(valueArray, 3);return 0;
}
//void show_2d(double valueArray[][5], int len)   两种头部书写方式都可以
void show_2d(double (*valueArray)[5], int len){for(int i = 0; i < len; i++){for(int j = 0; j < 5; j++){cout << *(*(valueArray +i) + j) << ",";}cout << endl;}
}

2.4 使用函数指针作为函数的参数

2.4.1 函数指针的基本内容

函数的地址是其机器语言代码在内存中存放的首地址
好处:将函数当作参数来传递,可以在不同的时间使用不同的函数
注意点:现有函数,先声明函数指针,再用函数指针指向需要的函数
使用场景:在很多函数调用的情况下,使用函数指针简化函数调用。

使用函数指针来指向一个函数的地址,函数指针的声明

//函数原型
double sum(double, double);
//函数指针声明, 一个指向函数的指针 ✅
double (*ptrSum)(double, double);
//返回值是double * 的函数, 达不到声明函数指针的效果
double *ptrSum(double, double);

demo1:用户幂函数的实现与对应的指针

#include "funptr.h" 
int main(){// 声明函数指针int (*ptrmypower)(int, int);// 让指针指向函数ptrmypower = my_power;// 用函数指针调用函数cout << ptrmypower(2, 3) << endl;cout << (*ptrmypower)(2,3) << endl;cout << my_power(2, 3) << endl;return 0;
}

funptr.h 文件内容

int power(int, int);int my_power(int num1, int num2){int result = 1;for(int i = 0; i < num2; i++){result *= num1;}return result;
}

demo2:使用函数指针实现加减乘除运算

#include "mycalc.h"
int main(){// 定义函数指针double (*ptrCalc)(double, double);double num1, num2;char op;cout << "请输入两个运算数字" << endl;cin >> num1 >> num2;cout << "请输入运算符" << endl;cin >> op;// seitch 语句只用来给函数指针赋值switch(op){case '+':// 调用加法函数ptrCalc = addtion;break;case '-':// 调用减法函数ptrCalc = subtraction;break;case '*':// 调用乘法函数ptrCalc = multiplication;break;case '\\':// 调用除法函数ptrCalc = division;break;}print_result(ptrCalc, num1, num2);return 0;
}

mycalc.h 中的内容

// 自定义计算器,使用函数指针
#include <iostream>
using namespace std;
/** 加法 */
double addtion(double, double);
/** 减法 */
double subtraction(double, double);
/** 乘法 */
double multiplication(double, double);
/** 除法 */
double division(double, double);
/** 打印结果*/
void print_result(double (*)(double, double), double, double);   // 把后两个duuble 传递给前面的函数指针ptrCalcvoid print_result(double (*ptrCalc)(double, double), double num1, double num2){// 调用函数,打印结果double result = ptrCalc(num1, num2);cout << "运算结果" << result << endl;
}double addtion(double num1, double num2){return num1 + num2;
}
double subtraction(double num1, double num2){return num1 - num2;
}double multiplication(double num1, double num2){return num1 * num2;
}double division(double num1, double num2){if(num2 == 0){cout << "除数不能为0" << endl;return 0;}else{return num1 / num2;}
}

2.4.2 函数指针数组的声明

–自行实践

double (*ptrCalc[])(double, double)

2.4.3 auto

函数指针的声明比较麻烦,C++ 11 中可以使用auto ptrFunc = addition; 实现函数类型的自动诊断(自动诊断需要确保变量的类型和赋值的类型一致),就可以不需要函数指针声明。

	// double (*ptrCalc)(double, double);auto ptrCalc = addtion;     // 必须初始化,遇到具体计算需求时,在赋予新的函数地址(如后续需要求减法)

2.4.4 使用typedef 定义函数指针类型

	typedef double (*ptrCalc)(double, double);  // 定一个了一个函数指针类型ptrCalc ptrCalc1;

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/444816.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

关于关闭SELinux的方法

原贴:http://www.diybl.com/course/6_system/linux/Linuxjs/2008629/129166.html关闭SELinux的方法&#xff1a;修改/etc/selinux/config文件中的SELINUX"" 为 disabled &#xff0c;然后重启。如果不想重启系统&#xff0c;使用命令setenforce 0注&#xff1a;seten…

leetcode739 每日温度

根据每日 气温 列表&#xff0c;请重新生成一个列表&#xff0c;对应位置的输入是你需要再等待多久温度才会升高超过该日的天数。如果之后都不会升高&#xff0c;请在该位置用 0 来代替。 例如&#xff0c;给定一个列表 temperatures [73, 74, 75, 71, 69, 72, 76, 73]&#…

scp免密码远程拷贝

有些时候&#xff0c;我们在复制/移动文件 到另一台机器时会用到scp&#xff0c;因为它比较安全。但如果每次都要输入密码&#xff0c;就比较烦了&#xff0c;尤其是在script里。不过&#xff0c;ssh有另一种用密钥对来验证的方式。下面写出我生成密匙对的过程&#xff0c;供大…

C++(13)--函数的进阶:内联、传递引用、参数默认值、重载、函数模板

模块化编程--函数的进阶1.内联函数1.1 inline基本情况1.2 inline 的前世今生-带参的宏替换2.传递引用&#xff08;重点&#xff09;2.1引用、理由、注意事项2.3 交换两个变量的数值3.返回引用3.1不要返回局部变量的引用3.2函数可以不返回值&#xff0c;默认返回传入的引用对象本…

终于,我读懂了所有Java集合——set篇

HashSet &#xff08;底层是HashMap&#xff09; Set不允许元素重复。 基于HashMap实现&#xff0c;无容量限制。 是非线程安全的。 成员变量 private transient HashMap<E,Object> map; // Dummy value to associate with an Object in the backing Map private s…

加速scp传输速度

当需要在机器之间传输400GB文件的时候&#xff0c;你就会非常在意传输的速度了。默认情况下(约125MB带宽&#xff0c;网络延迟17ms&#xff0c;Intel E5-2430&#xff0c;本文后续讨论默认是指该环境)&#xff0c;scp的速度约为40MB&#xff0c;传输400GB则需要170分钟&#xf…

tcpcopy使用方法

1、下载tcpcopy http://code.google.com/p/tcpcopy/downloads/list 2、配置、编译、安装 依此使用如下命令&#xff1a; 配置&#xff1a; ./configure 编译&#xff1a; make 安装&#xff1a; make install 3、使用方法 下面以mosquitto为例&#xff0c;说明tcpcopy的用法&a…

C++(14)--面向对象

面向对象1.面向对象编程(难点)2.类和对象demo1:地主类的实现版本1demo2:地主类的实现版本23.访问修饰符demo3:外部修改成员变量不安全(版本3)demo4: 使用封装防止直接修改成员变量&#xff08;版本3&#xff09;demo5:进一步封装&#xff1a;设置/获取名字&#xff0c;修改积分…

终于,我读懂了所有Java集合——map篇(多线程)

多线程环境下的问题 1.8中hashmap的确不会因为多线程put导致死循环&#xff08;1.7代码中会这样子&#xff09;&#xff0c;但是依然有其他的弊端&#xff0c;比如数据丢失等等。因此多线程情况下还是建议使用ConcurrentHashMap。 数据丢失&#xff1a;当多线程put的时候&…

system函数的返回值和执行脚本的返回值

1、先统一两个说法&#xff1a;&#xff08;1&#xff09;system返回值&#xff1a;指调用system函数后的返回值&#xff0c;比如上例中status为system返回值&#xff08;2&#xff09;shell返回值&#xff1a;指system所调用的shell命令的返回值&#xff0c;比如上例中&#x…

OJ汇总

国内&#xff1a;&#xff08;一下排名不分先后&#xff09; 浙江大学&#xff08;ZJU&#xff09;&#xff1a;http://acm.zju.edu.cn/ 北京大学&#xff08;PKU&#xff09;&#xff1a;http://acm.pku.edu.cn/JudgeOnline/ 同济大学&#xff08;TJU&#xff09;&#xff1a;…

C++(15)--面向对象编程实践-欢乐斗地主(vector的花式输出)

面向对象编程实践-欢乐斗地主《老九学堂C课程》《C primer》学习笔记。《老九学堂C课程》详情请到B站搜索《老九零基础学编程C入门》-------------简单的事情重复做&#xff0c;重复的事情用心做&#xff0c;用心的事情坚持做(老九君)---------------要求&#xff1a;实现录入及…

Google Protobuf 使用介绍

直接在 www.google.com.hk 上搜索google protobuf 后下载官方版本。 官方版本支持C\Java\Python三门语言。 还有很多非官方的语言版本支持&#xff0c;如C\NET(C#/Vb.net)\Flex(AS3)等. 要通信&#xff0c;必须有协议&#xff0c;否则双方无法理解对方的码流。在protobuf中&…

epoll的再次认识

使用mmap加速内核与用户空间的消息传递。 这 点实际上涉及到epoll的具体实现了。无论是select,poll还是epoll都需要内核把FD消息通知给用户空间,如何避免不必要的内存拷贝就很 重要,在这点上,epoll是通过内核于用户空间mmap同一块内存实现的。而如果你想我一样从2.5内核就关…

leetcode82. 删除排序链表中的重复元素 II

给定一个排序链表&#xff0c;删除所有含有重复数字的节点&#xff0c;只保留原始链表中 没有重复出现 的数字。 示例 1: 输入: 1->2->3->3->4->4->5 输出: 1->2->5 示例 2: 输入: 1->1->1->2->3 输出: 2->3 思路&#xff1a;判断n…

C++(16)--运算符重载(自定义Integer类)

运算符重载1.运算符重载--重点2.友元函数--难点(流运算符重载)《老九学堂C课程》《C primer》学习笔记。《老九学堂C课程》详情请到B站搜索《老九零基础学编程C入门》 -------------简单的事情重复做&#xff0c;重复的事情用心做&#xff0c;用心的事情坚持做(老九君)--------…

反应器组件 ACE_Reactor

6.1 反应器组件 ACE_Reactor反应器的基本原理是: 针对关心的某个事件写一个事件处理器(event_handler). 将该事件处理器登记到反应器中(同时指明关心的事件). 然后反应器会自动检测事件的发生. 并调用预先登记的事件处理器中的回调函数. 所以ACE Reactor 框架的责任&#x…

C++(17)--详解const

详解const《老九学堂C课程》《C primer》学习笔记。《老九学堂C课程》详情请到B站搜索《老九零基础学编程C入门》-------------简单的事情重复做&#xff0c;重复的事情用心做&#xff0c;用心的事情坚持做(老九君)---------------1.const修饰成员变量 2.const修饰函数参数 3.c…

cppcheck的安装和使用

首先从这里下载linux版本的:http://sourceforge.net/projects/cppcheck/files/cppcheck/ 然后下载对应的版本,解压,之后安装: 编译: g++ -o cppcheck -Ilib cli/*.cpp lib/*.cpp 安装: make install

leetcode24 两两交换链表中的节点

给定一个链表&#xff0c;两两交换其中相邻的节点&#xff0c;并返回交换后的链表。 你不能只是单纯的改变节点内部的值&#xff0c;而是需要实际的进行节点交换。 示例: 给定 1->2->3->4, 你应该返回 2->1->4->3. 思路&#xff1a;这一看就是个递归定义&…