函数指针的作用:*visit函数

定义

函数指针是指向函数的指针变量。 因此“函数指针”本身首先应是指针变量,只不过该指针变量指向函数。这正如用指针变量可指向整型变量、字符型、数组一样,这里是指向函数。如前所述,C在编译时,每一个函数都有一个入口地址,该入口地址就是函数指针所指向的地址。有了指向函数的指针变量后,可用该指针变量调用函数,就如同用指针变量可引用其他类型变量一样,在这些概念上是大体一致的。函数指针有两个用途:调用函数和做函数的参数。

int f(elementtype x);  //声明函数
int (*f1)(elementtype x); //声明函数指针
f1=f;//函数首地址赋值
f1=&f; //函数地址赋值

示例:(使用方法)

#include<stdio.h>
int max(int x,int y){return (x>y? x:y);}
int main()
{
    int (*ptr)(int, int);
    int a, b, c;
    ptr = max;
    scanf("%d%d", &a, &b);
    c = (*ptr)(a,b);
    printf("a=%d, b=%d, max=%d", a, b, c);
    return 0;
}

作用

 个人感觉函数指针最大的作用就是作为函数的参数,当函数需要一个函数作为形参,而这个函数形参未定义或者不确定应该输入哪个函数时,函数指针的作用就体现出来了,使用地址传递的方式,利用函数指针作为形参可以很好地解决这个问题,这有利于程序的模块化与封装性
 例如:像二叉树遍历中使用的*visit()函数指针,我们并不清楚,visit应该是输出、操作、赋值等等哪一个函数,因此使用*visit函数指针,等实际输入时再确定它是哪一个函数。
template<class T>
void BinTree<T>::Preorder(BinTreeNode<T> *subtree,void (*visit)(BinTreeNode<T> *s)){
    if(subtree!=NULL){
        visit(subtree);
        Preorder(subtree->leftChild,visit);
        Preorder(subtree->rightChild,visit);
    }
 }
void printnode(BinTreeNode<char> *tnode){
     cout<<tnode->data<<' ';
}
int main(){
    BinTree<char> t;
    t.buildtree();
    t.Levelorder(printnode);
    t.Inorder(printnode);
    return 0;
}

函数指针模板

我们可以将printnode函数定义为模板函数

template<class T> void printnode(BinTreeNode<T> *tnode){
     cout<<tnode->data<<' ';
}

但如果在主函数里定义visit的函数指针模板, 直接如下所示

template<class T> void (*visit)(BinTreeNode<T> *tnode);

c++会报错,(原因我也不太清楚)

解决方法: 把函数指针封装在一个模板结构或模板类里,像在BinTree类中,我们定义一个模板函数指针就可以通过

template <class T>
struct Type {
   void (*visit)(BinTreeNode<T> *tnode)};

或是放到一个模板函数内,让函数指针作为一个形参,在函数内再调用指针指向的函数,但这样也就没有特意定义它的必要,他也就像二叉树遍历函数中的用法一样,作为函数形参,不需要特别定义。

template <class T> void Func( void (*visit)(BinTreeNode<T> *tnode),BinTreeNode<T> *tnode) {
  printnode(BinTreeNode<T> *tnode);
}
  • 20
    点赞
  • 72
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值