我们都知道C语言是一门面向过程的语言,那么C语言如何实现“面向对象”的编程方式呢?今天我们就来一探究竟
一、C实现面向对象的基石—-函数指针:
1、什么是函数指针:
我们也许听过一级指针(指向普通变量的指针)、二级指针(指向指针的指针)、数组指针(指向数组的指针)、指针数组(数组元素是指针)等概念,那么函数指针是什么呢?顾名思义,从表象上来说:函数指针就是指向函数的指针,但终究它也只是一个指针。怎么说是指向函数的指针呢?请看下例:
void (*test)(void);
/*
格式如此:定义分为三部分,返回值类型、指针名、参数类型。
该语句定义了一个指向“无参数无返回值的函数”指针。
注意:中间(*test)的括号不能省略
*/
2、那么函数指针到底该怎么用呢?举个简单的例子:
# include<stdio.h>
int test_one(int num1, int num2)
{
return num1 + num2;
}
int test_two(int num1, int num2)
{
return (num1 - num2);
}
int main(void)
{
int (*test[5])(int,int);/*定义一个有五个函数指针的数组*/
test[0] = test_one;/*让数组中第一个元素(函数指针)指向test_one函数*/
test[1] = test_two;/*让数组中第二个元素(函数指针)指向test_two函数*/
printf("test_one return value = %d\n",test_one(10,5));
printf("test_two return value = %d\n",test_two(10,5));
printf("test[0] return value = %d\n",test[0](10,5));
printf("test[1] return value = %d\n",test[1](10,5));
}
3、测试结果如下所示:
由于函数名本来就是一个指针,而将函数名赋给一个与其类型的相同的指针(函数指针),使用函数指针也就和使用函数名效果一样了。
二、使用函数指针实现C的面向对象:
1、思路:
面向对象,在C++中用的类来实现,而我们都知道在C++中结构体是一种特殊的类(类(class)其默认成员是私有的,而结构体默认成员是公有的),那么我们就在C中就可以使用结构体来实现统一封装与调用。
2、基本实现代码:
这里我将几种对数组的排序函数封装成一类方法,代码如下:
# include<stdio.h>
# include<stdlib.h>
# include<time.h>
struct Sort_Arr{
int * arr;
void (*print_arr)(int *,int);//遍历
void (*sort_bubble)(int *,int);//冒泡排序
void (*sort_insert)(int *, int);//插入排序
void (*sort_choose)(int *, int);//选择排序
void (*sort_quickly)(int *, int, int);//快速排序
int (*find_pos)(int *, int, int);//快排找pos
int * (*rand_arr)(int);//生成随机数数组
};
void Print(int *a,int len)
{
if(0 == len)
{
printf("数组为空!\n");
return;
}
int i=0;
for(i=0;i<len;++i)
printf("%d ",a[i]);
printf("\n");
}
void SortBubble(int *a,int len)
{
int i, j, temp;
for(i=0;i<len;i++)
for(j=0;j<len-i-1;j++)
if(a[j] > a[j+1])
{
temp = a[j];
a[j] = a[j+1];
a[j+1] = temp;
}
}
void SortChoose(int *a,int len)
{
//每次寻找剩余区间最小值,将最小值与区间首元素互换后,区间大小减1(区间首元素后一个元素开始继续循环找最小值)
int i,j,tmp,min;
for(i=0;i<len;i++){
min = a[i];
tmp = i;
for(j=i+1; j<len; j++){
if(a[j] < min){
min = a[j];
tmp = j;
}
}
if(tmp != i){
a[tmp] = a[i];
a[i] = min;
}
}
}
void SortInsert(int *a,int len)
{
//在原有有序的基础上,将紧邻的无序区间首元素插入有序区间,之后有序区间长度加1,无序区间长度减1
int i,j,k,temp;
for(i=1;i<len;++i)
{
temp = a[i];
j = i-1;
while(j >= 0 && a[j] > temp){
a[j+1] = a[j];//后移
j--;
}
a[j+1] = temp;
}
}
void SortQuickly(int *a, int low, int high)
{
int pos;
if(low < high)
{
pos = FindPos(a, low, high);
SortQuickly(a, low, pos-1);
SortQuickly(a, pos+1, high);
}
}
int FindPos(int *a,int low,int high)
{
int key = a[low];
while(low < high)
{
while(low < high && (a[high] >= key))
high--;
a[low] = a[high];
while(low < high && (a[low] <= key))
low++;
a[high] = a[low];
}
a[low] = key;
return low;
}
int * RandArr(int n)
{
int i;
int * a = (int *)malloc(sizeof(int) * n);
if(NULL == a)
{
printf("内存分配失败导致数组创建失败!");
exit(EXIT_FAILURE);
}
srand(time(NULL));
for(i=0; i<n; i++)
a[i] = rand()%51-25;//生成-25~45之间的随机数数组
return a;
}
int main (void)
{
struct Sort_Arr SORTARR = {
.print_arr = Print,
.sort_bubble = SortBubble,
.sort_insert = SortInsert,
.sort_choose = SortChoose,
.sort_quickly = SortQuickly,
.rand_arr = RandArr
};
int len;
int choose;
printf("请输入要生成的数组元素个数:\n");
scanf("%d",&len);
SORTARR.arr = SORTARR.rand_arr(len);
printf("生成的数组为:\n");
SORTARR.print_arr(SORTARR.arr,len);
printf("(1)冒泡排序\t(2)插入排序\t(3)选择排序\t(4)快速排序\n");
printf("请输入你要选择的排序方式序号,回车结束:\n");
scanf("%d",&choose);
switch(choose)
{
case 1:SORTARR.sort_bubble(SORTARR.arr,len);
break;
case 2:SORTARR.sort_insert(SORTARR.arr,len);
break;
case 3:SORTARR.sort_choose(SORTARR.arr,len);
break;
case 4:SORTARR.sort_quickly(SORTARR.arr,0,len);
break;
default:printf("其他排序方式正在研制中,请稍候...");
break;
}
printf("排序后的数组为:\n");
SORTARR.print_arr(SORTARR.arr,len);
return 0;
}
将此代码稍作修改,制作成静态库或动态库,以后就可以直接使用写好的排序函数了。