zoukankan      html  css  js  c++  java
  • [C++] 函数指针的学习与运用

    什么是函数指针

      函数指针:如果在程序中定义了一个函数,那么在编译时系统就会这个函数代码分配一段存储空间,这段存储空间的首地址称为这个函数的地址。

    函数指针变量定义形式

    函数返回值类型 (*函数指针变量名) (函数参数列表);

    如何用函数指针调用函数

    int max(int x, int y);   /*声明一个函数*/
    int (*pMax) (int x, int y);  /*定义一个函数指针*/
    pMax = max;          /*将max函数的首地址赋给指针变量p*/

    使用实例

    #include <iostream>
    using namespace std;
    
    int max(int x, int y);
    
    int main(int argc, char const *argv[])
    {
        int (*pMax)(int, int);
        pMax = max;
        int max_val = pMax(10, 100);
        cout << max_val << endl;
        return 0;
    }
    
    int max(int x, int y)
    {
        return x>y ? x : y;
    }
    

      

    为某一函数型定义其函数指针类型

     定义语句

    typedef (*函数指针类型名)(函数参数列表);
    
    /*e.g*/
    typedef int(*max_func_type)(int, int);
    

      这个就可以用像定义普通变量一样,定义一个函数指针变量了,前面的例子可以改成如下:

    #include <iostream>
    using namespace std;
    
    int max(int x, int y);
    
    typedef int(*max_func_type)(int, int);
    
    int main(int argc, char const *argv[])
    {
        max_func_type pMax = max;  /*这就很符合平常定义变量的语法*/
        int max_val = pMax(10, 100);
        cout << max_val << endl;
        return 0;
    }
    
    int max(int x, int y)
    {
        return x>y ? x : y;
    }
    

      

    函数指针的高级使用

      开发过程中,需要用到某个dll库文件时,但只有说明文档,而开发用的lib文件和头文件都丢失了,这种情况下怎么办?方法就是:

    1. 使用HMODULE hModule = LoadLibrary(LPCTSTR lpFileName)加载这个dll文件,
    2. 再用GetProcAddress(hModule, "函数名")获取需要调用的函数的内存地址(函数指针)。

       还是前面的例子,把max()函数封装到一个dll里,代码如下:

    /*CMakeLists.txt*/
    cmake_minimum_required(VERSION 3.0)
    
    project(max)
    
    FILE(GLOB SC "*.cpp" "*.h")
    
    add_library(${PROJECT_NAME} SHARED ${SC})
    

      

    /*max.h*/
    #ifndef __MAX_H__
    #define __MAX_H__
    
    extern "C" __declspec(dllexport) int __cdecl max(int x, int y);  /*注意这里*/
    
    #endif // !__MAX_H__
    

      上面需要注意的那一行,为了让max函数在dll文件的导出表里的名称就是“max”,其实我有点偷懒了,正确的声明应该是把__cdecl 换成 __stdcall,这样才符合GetProcAddress()返回的函数指针对应的函数调用规范,但用了__stdcall后,dll中的导出函数名就不是简单的“max”了。至于函数调用规范的内容,就可能开另外一个单章进行总结了。有兴趣的可以网上搜,自个进行了解。

    /*max.cpp*/
    #include "max.h"
    
    int __cdecl max(int x, int y)
    {
    	return x > y ? x : y;
    }
    

      在另外一个项目中使用上面封装的dll,注意只要dll文件,lib文件与头件别也复制过来了:

    /*CMakeLists.txt*/
    cmake_minimum_required(VERSION 3.0)
    
    project(LoadDll)
    
    FILE(GLOB SC "*.cpp" "*.h")
    
    add_executable(${PROJECT_NAME} ${SC})
    

      

    /*main.cpp*/
    #include <Windows.h>
    #include <iostream>
    using namespace std;
    
    typedef int(*max_func_type)(int, int);
    
    int main(int argc, char** argv)
    {
    	HMODULE hDll = LoadLibrary("max.dll"); /*加载dll文件*/
    	if (!hDll)
    	{
    		cerr << "Load max.dll error" << endl;
    	}
    
    	max_func_type pMax = (max_func_type)GetProcAddress(hDll, "max");  /*获取函数地址,赋值函数指针变量pMax*/
    	if (!pMax)
    	{
    		cerr << "function max not found" << endl;
    	}
    	else 
    	{
    		int ret = pMax(100, 10);  /*通过函数指针调用max函数*/
    		cout << "result: " << ret << endl;
    	}
    	FreeLibrary(hDll);
    	return 0;
    }
    

      

    PS:其实还有一个进阶的用法, 就是已经有一段编译好,且可独立运行的代码(目标代码),先加载到内存,把对应的内存地址赋值给一个函数指针,方便后面的调用,但这里涉及到一个内存权限问题,一般这样的加载只有可读写权限,但调用是需要执行权限的,这就需要调用系统API对这段内存进行赋权!!

  • 相关阅读:
    用before 和after 清除浮动
    清除浮动最优
    pc端布局03
    PC端布局02
    >PC端常用布局01
    浮动
    盒模型-
    盒模型-外边距合并
    spring中的AOP
    AOP的概念
  • 原文地址:https://www.cnblogs.com/dilex/p/13518514.html
Copyright © 2011-2022 走看看