第二章整理(面向过程的编程风格)

本文围绕C++函数展开,介绍了函数的编写、调用方式,包括传值和传址。还阐述了默认参数值、局部静态对象、inline函数、重载函数、模板函数、函数指针等特性,以及头文件的使用,强调函数声明与定义的规则和函数指针的应用限制。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1.编写函数

  • 返回类型
  • 函数名
  • 参数列表

必须先声明,定义可以延后

  • 返回值

必须在每个可能的退出点上将值返回,函数体的最后一句不是return,则这一句就是函数的隐式退出点

2.调用函数

  • 传值

传值时,传入的值和原来的值得唯一的联系,就是值相同,相当于复制了一份,在我们调用函数的时候,会在内存中建立一个特殊区域,程序堆栈,为每个函数的参数提供存储空间,一旦函数完成,内存就会释放。这些对象为局部对象

  • 传址

传址的方式传入函数的是对象的地址,而不是复制的一份,采用引用的方式传入。

void display(const vector<int> &vec){
	for(int i=0;i<vec.size();i++){
		cout << vec[i] << " ";
		cout << endl;
	}
}
  • 作用域和范围

函数内定义的对象,只存在于函数执行的期间,如果把这些局部对象的地址返回,会出错。

int* display(const vector<int> &vec){
	int a;
	a=3;
	return &a;
}

3.默认参数值

void display(const vector<int> &vec,ostream &os=cout){
	for(int i=0;i<vec.size();i++){
		os << vec[i] << endl;
	}
}

定义一个ostream的对象,将其的初值赋值为cout,这样默认的是打印在屏幕上,也可以选择输出到文件中。

4.局部静态对象

const vector<int> *seq(int size){
	static vector<int> elems;
	return &elems;
}

此时函数可以返回静态局部变量的地址,因为在函数执行结束的时候,elem并不会从内存中消失,依然存在,其存在的范围是当前的文件中。

5.inline函数

inline函数的作用,就是声明当前的函数,要求编译器在每个函数的调用点上,将函数展开。

6.重载函数

不能根据返回值的类型来重载函数,而是参数列表中,参数类型以及参数数量的不同

7.模板函数

template <typename elemtype>
void display_message(const string &msg,const vector<elemtype> &vec){
	cout << msg;
	for(int i=0;i<vec.size();i++){
		elemtype t=vec[i];
		cout << t << ' ';
	}
}

其实就是定义一个类型,函数不指定类型的输入,elemtype是一个暂时存放类型的占位符。

8.函数指针

首先要注意

int *f(int i, int j);

int (*p)(int i, int j);

第一个是返回指针的函数,第二个是指向函数的函数指针,

函数名和数组类似,也是代表函数所存放的地址,函数名就代表了函数的地址。

  • 函数指针的定义

将函数名换成指针,同时制定参数列表。

double add(double x, double y)
{
    return x + y;
}

//函数指针
double (*pf)(double,double)=add;  //这里(*pf)的括号不能省,不然就不是函数指针了。
  • 函数指针的数组
double add(double x, double y)
{
	return x + y;
}

double add2(double x, double y)
{
	return x - y;
}
double (*pf[2])(double,double) = { add, add2 };

pf是有2个函数指针的数组

  • 应用

对于第一种,

#include<iostream>
using namespace std;
double add(double x, double y)
{
	return x + y;
}

double calculate(double x1, double y1, double(*f)(double, double)) 	//函数调用里面传递 函数指针数组 的方法
{
	cout << "add:" << (*f)(x1, y1) << endl;
	return 1;
}

int main(){
	double (*pf)(double,double)=add; //这里(*pf)的括号不能省,不然就不是函数指针了。
	int x = 2,y = 1;
	calculate(x, y, pf);
	//直接calculate(x, y, add);也是可以的 
}

第二种:

#include "iostream"
 
using namespace std;
 
double add(double, double);
double add2(double x, double y);
 
double calculate(double x1, double y1, double(*f[])(double, double))  //函数调用里面传递 函数指针数组 的方法  
{
    cout << "add:" << (*f[0])(x1, y1) << endl;
    cout << "add2:" << (*f[1])(x1, y1) << endl;
    return  1;
}
 
int main()
{
    int x, y;
    double (*pf[2])(double,double) = { add, add2 }; //
    x = 2; y = 1;
    calculate(x, y, pf);  //注意此处的pf,他是函数的名字,就是指针,而这个指针指向的还是指针,即add这个函数名(函数名也是指针),所以在calculate函数的定义中,要用(*f[])或者(**f)
 
    system("pause()");
    return 0;
}
 
 
 
double add(double x, double y)
{
    return x + y;
}
 
double add2(double x, double y)
{
    return x - y;
}

然后建立函数数组并赋值  double (*pf[2])(double,double) = { add, add2 }; 
接着传递给上面定义的calculate函数。调用方式为:calculate(x, y, pf);

calculate函数的接收方式应为:double calculate(double x1, double y1, double(**f)(double, double)) //传递的pf是一个数组的数组名且本身也是一个指针,即为二重指针     或者double calculate(double x1, double y1, double(*f[])(double, double))

 同时,函数指针不支持自加和自减

函数指针指向的是函数入口地址,每个函数占用的空间是不同的,所以指针增减时就无法确定指针的移动范围,自然没办法指向相邻函数了。

void test(void){
    static int temp = 1;
}

int table[5]= {0};

void main(){
    printf("数组地址1=%p\n", &table); 
    printf("数组地址2=%p\n", table);
    printf("数组地址3=%p\n",&table+1); 
    printf("数组地址4=%p\n", table+1); 
    printf("函数地址1=%p\n", &test);     //&test和test其实是一样的,都是函数的地址
    printf("函数地址2=%p\n", test); 
    printf("函数地址3=%p\n", &test+1); // 这个报错
    printf("函数地址4=%p\n", test+1); //这个也报错
}


9.头文件

将函数的声明放在头文件中,方便多个程序调用 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值