首页 > 代码库 > 大话 函数指针 和 枚举这对鸳鸯

大话 函数指针 和 枚举这对鸳鸯

一:起因

1函数指针是指向函数的指针变量,即本质是一个指针变量,是一个指向函数(可能是代码区)的首地址的指针,正如我们都知道,数组名就是指向数组第一个元素的常量指针,对于一个函数而言,函数名也是指向函数第一条指令的常量指针。大话 回调函数 和 枚举

(2)而回调函数就是C语言里面对函数指针的高级应用,回调函数是一个通过函数指针调用的函数。如果你把函数指针(函数的入口地址)传递给另一个函数,当这个函数指针被用来调用它所指向的函数时,我们就说这个函数是回调函数。 大话 函数指针 和 指针函数

(2-2)为何要用枚举?一个星期只有七天,一年只有十二个月。如果把这些量说明为整型,字符型或其它类型显然是不妥当的。为此,程序设计语言提供了一种枚举类型(也称为枚举)。

(3)  枚举的声明,其形式为:(枚举名称相当于这个集合的名字,可有可无;类型定义以分号(;)结束),每一个成员的取值一定不要超过定义的范围。

访问修饰符 enum 枚举名:基础类型 { 枚举成员(标识符)}

(4)每个枚举成员均具有相关联的常数值,此值的类型就是枚举的基础类 型。枚举类型属于顺序类型,这样每一个枚举成员都代表一个值(int bool等),这样就可以用作函数数组的下标值。(枚举成员类型可以是除char 以外的任何整型)

二:详细解释

1)   枚举成员不能是数值常量、字符常量、字符串常量,使用时不能加单、双引号。例如,以下的定义是错误的:

enum Days { ‘Sun’, ‘Mon’, ‘Tues’, ‘Wed’, ‘Thu’, ‘Fri’,‘Sat’ }

enum Days { “Sun”, “Mon”, “Tues”, “Wed”, “Thu”, “Fri”,“Sat” }

2)    每个枚举成员均具有相关联的常数值。此值的类型就是枚举的基础类 型。枚举类型属于顺序类型。根据定义类型时各枚举成员的排列顺序确定它们的序列,如在默认基础类型即int的情况下序列号从0开始,后面每个枚举成员的值依次递增 1。当然可以显式赋值。例如:

enum Days { Sunday=2, Monday, Tuesday, Wednesday,Thursday, Friday, Saturday }

枚举成员是常量,不是变量。尽管是标识符也不能在程序中当做变量用赋值语句对它赋值。

3)  枚举的声明,其形式为:(枚举名称相当于这个集合的名字,可有可无;类型定义以分号(;)结束),每一个成员的取值一定不要超过定义的范围。

访问修饰符 enum 枚举名:基础类型 { 枚举成员(标识符)}
说明:任意枚举类型都有基础类型,该基础类型可以是除char 以外的任何整型,如:byte、sbyteshortushortintuintlongulong。基础类型必须能够表示该枚举中定义的所有枚举成员。枚举声明时可以对基础类型进行显式地声明。而没有显式声明时基础类型默认是 int。基础类型指定为每个枚举数成员分配的内存大小。

4)设有变量a,b,c被说明为上述的Days,可采用下述任一种方式:相邻的每个枚举成员用逗号(,)隔开;最后一个没有逗号。  枚举类经常用在switch-case结构中,其常用的(Enum)方法主要有以下几个:

三:应用实例

(1)举个例子: 学生 类分大学生 高中 初中小学生 你就可以这么做 

enum student{colleage,high,middle,junior} 

//小明是个大学生 

student xiaoming=colleage; 

//判断小刚是不是高中生 

if(xiaogang==high)

(2) 枚举元素本身由系统定义了一个表示序号的数值,(枚举元素是数值了)从0开始顺序定义为0,1,2…。如在weekday中,sun值为0,mon值为1,…,sat值为6。  

int main()

       enum weekday { sun,mon,tue,wed,thu,fri,sat } a,b,c;

        a=sun; b=mon; 

       c=tue; 

       printf("%d,%d,%d",a,b,c); 

}

说明: 

只能把枚举值赋予枚举变量,不能把元素的数值直接赋予枚举变量。如:

 a=sum; b=mon; 是正确的。

而: a=0;  b=1;  是错误的。

如一定要把数值赋予枚举变量,则必须用强制类型转换。 如: 

a=(enum weekday)2; 

其意义是将顺序号为2的枚举元素赋予枚举变量a,相当于: 

a=tue; 

还应该说明的是枚举元素不是字符常量也不是字符串常量,使用时不要加单、双引号。枚举成员是常量,不是变量。尽管是标识符也不能在程序中当做变量用赋值语句对它赋值。

int main()
{ 
	enum body { a,b,c,d } month[31],j;
	 int i;
	 j=a; 
	for(i=1;i<=30;i++)
	{ 	
		month[i]=j;
		 j++; 
		if (j>d)	 j=a; // 可以看出枚举元素相当于被定义为固定值的常量了
	} 
	for(i=1;i<=30;i++)
	{
		switch(month[i]) 
		{ 
			case a:printf(" %2d %c\t",i,'a'); break; 
			case b:printf(" %2d %c\t",i,'b'); break; 
			case c:printf(" %2d %c\t",i,'c'); break; 
			case d:printf(" %2d %c\t",i,'d'); break; 
			default:break;
		 } 
	} 
	printf("\n"); 
} 

(3)完整的例子,可以和对比,发现下面的优点

#include <iostream>
using namespace std;

double add(double, double);
double sub(double, double);
double mul(double, double);
double div(double, double);
// 或者其它的指针
double (*oper_func[])(double, double)={
    add,sub,mul,div
    };
double calculate(double, double, double (*func)(double,double));
enum operations{
add_ = 0,
sub_ = 1,
mul_ = 2,
div_ = 3
};


 int main(){
    operations operation = sub_;
    cout << operation << endl;
     double op1,op2;
     cin >> op1 >> op2;
     int index = 0;// index 可以根据需要进行更改
     //double result = oper_func[index](op1,op2);//
     double result = calculate(op1,op2,oper_func[sub_]);// 这样在真正的工程中,根据实际的字符串名称处理问题了,
     // 而且可以不用考虑字符串所对应的数值是否会越界等问题,因为枚举成员是固定在某一个取值范围内的。
     cout << "result= " << result << endl;
        return (0);
 }
double calculate(double op1, double op2, double (*func)(double,double))
{
    return func(op1,op2);
}

double add(double op1, double op2)
{
    return op1 + op2;
}

double sub(double op1, double op2)
{
    return op1 - op2;
}
double mul(double op1, double op2)
{
    return op1 * op2;
}
double div(double op1, double op2)
{
    if(op2 != 0)
        return op1 / op2;
    return -1;// 失败了
}
解释:这样就可以通过枚举类型(enum operators)和函数指针数组( double (*oper_func[])(double, double) = { }  ),以及回调函数(  double calculate(double op1,double op2, double (*func)(double,double) )     )  代替了复杂的swich-case句型

double calculate(double op1, double op2, double (*func)(double,double))
{
    return func(op1,op2);
}
当然,目前的代码仍然有需要改进的地方,例如:计算那一步,只能计算double类型的数据,所以需要优化来实现计算任何类型的数据。

(4)插入错误解释方法  undefined reference

最近在Linux下编程发现一个诡异的现象,就是在链接一个静态库的时候总是报错,类似下面这样的错误:

~~~~~~~ undefined reference to `func‘

这就是最典型的undefined reference错误,因为在链接时发现找不到某个函数的实现文件,(一句话就是缺少函数的实现部分,仅仅写出了声明部分是不行的)

大话 函数指针 和 枚举这对鸳鸯