C++基础知识(六)

函数指针

函数指针的目的与意义:抽象数据与抽象代码
函数的地址:函数入口位置,将该数值作为数据保存起来,就可以通过特殊手段调用该函数
typedef void* ADT;
typedef const void * CADT;

  1. 函数指针的定义
    数据类型 (as_string)(ADT object);
    as_string作为变量可以指向任何带有一个ADT类型参数的返回值char
    类型的函数
    函数指针变量可以像普通变量一样赋值
    函数指针数据对象名称=函数名称
    char* DoTransformObjectIntoString(ADT object)
    {return PtTransformIntoString((PPoint)object);}
    as_string = DoTransformObjectIntoString;
  2. 函数指针的使用
    通过函数指针调用函数
    通过指针被赋值后,即指向实际函数的入口地址
    通过函数指针可以直接调用它所指向的函数
    调用示例:
    char* returned_value;
    PPOINT pt=PtCreate(10, 20);
    as_string = DoTransformObjectIntoString;
    returned_value=as_string((ADT)pt);
    需要区分函数指针调用和函数指针直接调用,使用下述格式调用函数指针指向的函数:
    returned_value = (*as_string)((ADT)pt);

设计程序,随机生成8个10~99之间的整数,调用stdlib库的qsort函数对其进行排序
qsort函数原型
void qsort(void base, unsigned int number_of_elements, unsigned int size_of_elements, int (compare)(const void, const void ));
调用时需按照下述格式实现自己的比较函数
int(compre)(const void,const void
);
比较函数示例:
int MyCompareFunc(const void
e1, const void* e2);
比较函数必须返回正负值(一般为正负1或0),规则按照题目要求自定义

示例:

//main.cpp
#include <iostream>
#include <cstdlib>
using namespace std;
#include "arrmanip.h"
#define NUMBER_OF_ELEMENTS 8
int DoCompareObject(const void* e1, const void* e2);

int main()
{
	int a[NUMBER_OF_ELEMENTS];
	GenerateIntegers(a, NUMBER_OF_ELEMENTS);
	cout<<"Array generated at random as follows:"<<endl;
	PrintIntegers(a, NUMBER_OF_ELEMENTS);
	qsort(a, NUMBER_OF_ELEMENTS, sizeof(int), DoCompareObject);
	cout<<"After sorted:"<<endl;
	PrintIntegers(a, NUMBER_OF_ELEMENTS);
	return 0;
}
int DoCompareObject(const void*e1, const void*e2)
{
	return CompareInteger(*(const int*)e1, *(const int*)e2);
}

//arrmanip.h
void GenerateIntegers(int a[], unsigned int n);
int CompareInteger(int x, int y);
void PrintIntegers(int a[], unsigned int n);

//arrmanip.cpp
#include <iostream>
using namespace std;
#include "random.h"
#include "arrmanip.h"

static const unsigned int lower_bound=10;
static const unsigned int upper_bound=99;

void GenerateIntegers(int a[], unsigned int n)
{
	unsigned int i;
	Randomize();
	for(i=0;i<n;i++)
	{
		a[i]=GenerateRandomNumber(lower_bound, upper_bound);
	}
}

函数指针的赋值
同类型函数指针可以赋值,不同类型则不能赋值
如何确定函数指针类型是否相同:函数参数与返回值不完全相同
函数指针类型:用于区分不同类型的函数指针
typedef int (COMPARE_OBJECT)(const voide1, const voide2);
前面添加typedef 关键字,保证COMPARE_OBJECT为函数指针类型,而不是函数指针变量
可以像普通类型一样使用函数指针类型定义变量:
COMPARE_OBJECT compare=DoCompareObject;
qsort函数的简明写法
void qsort(void
base, unsigned int number_of_elements,unsigned int size_of_elements,COMPARE_OBJECT compare);

  1. 抽象列表
    1、回调函数:允许通过函数指针调用未来才会实现的代码
    回调函数:依赖后续设计才能确定的被调函数
    示例:DoCompareObject
    2、回调函数参数
    回调函数与主调函数的信息交互:附加信息
    3、数据对象的存储与删除
    删除链表结点时,其中的目标数据对象是否需要删除?
    如果链表结点存储的是指针,就需要删除,否则不需要
    设计抽象链表时候,并不了解结点实际存储的数据是否为指针,因而无法确定结点数据操作逻辑
  2. 回调函数
    编写函数,遍历链表,结点数据的具体操作方法目前未知,由未来的回调函数提供
typedef void (*MANIPULATE_OBJECT)(ADT e);
void LlTraverse(PLIST list, MANIPULATE_OBJECT manipulate)
{
	PNODE t=list->head;
	if(!list)
	{	cout<<"LlTraverse:Parameter illegal."<<endl;
		exit(1);
	}
	while(t)
	{
		if(manipulate)  //通过函数指针调用实际函数操纵目标数据对象*manipulate)(t->data);
		t=t->next;
		
	}
}


//回调函数参数
typedef void (*MANIPULATE_OBJECT)(ADT e, ADT tag);
void LlTraverse(PLIST list, MANIPULATE_OBJECT manipulate, ADT tag)
{
	PNODE t=list->head;
	if(!list)
	{	cout<<"LlTraverse:Parameter illegal."<<endl;
		exit(1);
	}
	while(t)
	{
		if(manipulate)  //通过函数指针调用实际函数操纵目标数据对象*manipulate)(t->data, tag);
		t=t->next;
		
	}
}


//示例
//点数据到字符串的转换函数,最终程序员任意定义
//参数format表示点数据对象的转换格式
//其中只能表示两个格式%d,其它内容任意
//例如格式"[%d, %d]","(%d, %d)"等
char* PtTransformIntoString(const char* format, PPoint point)
{
	char buf[BUFSIZ];
	if(point)
	{	
		sprintf(buf, format, point->x, point->y);
		return  DuplicateString(buf);
	}
	else
		return "NULL";
}

//回调函数DoPrintObject
void DoPrintObject(ADT e, ADT tag)
{
	printf(PtTransformIntoString((const char*)tag, ((PPOINT)e));
	printf("->");
}
//回调函数参数的意义
//调用遍历函数时将点数据的输出格式传递给遍历函数,再由遍历函数传递给回调
LlTraverse(list, DoPrintObject, "(%d, %d)");
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值