C++类的函数指针成员

原创 2018年04月17日 12:24:06

一、函数指针基础

1. C/C++ 函数指针使用总结

2. C++ 函数指针取地址与取值

二、类的函数指针成员

前面两篇文章中提到,函数指针也是一种指针变量,因此将函数指针指向参数和返回值(也就是函数签名)相同、但实现不同的函数,通过函数指针来调用函数时,就能表现出不同的行为。

通常来将,类的函数指针成员可以指向这三类函数:

1. 普通函数,直接赋值,''函数指针''="函数名"

2. 类的友元函数,直接赋值,''函数指针''="函数名"。类的友元函数可以访问类的私有变量。

3. 类的静态成员函数,赋值,''函数指针''="类名::函数名".

需要指出的是,类的函数指针无法指向非静态成员。

三、例子

这部分给出函数指针指向类的静态函数的例子,为了能在静态函数中访问类的成员,在静态函数中增加一个参数来指向一个实例。

/**
 * 1.Array是一个模板类,作用类似于一个vector,但是只实现了部分函数。
 * 最大的特点是在多线程环境下通过指针访问数组的元素的是安全的,不会
 * vector一样出现非法指针,详见博客:
 * https://blog.csdn.net/DumpDoctorWang/article/details/79966945
 *
 * 2.设计思想是,每当向Array数组的末尾push一个元素时,不是直接将数
 * 据本身放进数据容器,而是new一块空间,把数据的值放进去,由于new
 * 的空间需要手动释放才会失效,因此通过指针访问数组的元素时,除非手
 * 动释放了空间,都不会出现异常。然后将新分配空间的指针存储在vector
 * 里,这样就可以通过指针访问数组元素。这部分详见push()的实现。
 *
 * 3.这个类实现了一种可以在参数不同的情况下,调用同一个成员函数表现出
 * 不同的行为的代码。具体思想是:
 * 首先定义一个函数指针f,在构造函数中根据参数的不同将f指向本类的参数
 * 相同、实现不同的静态函数。在调用的时候,就通过指针f来调用函数。这样
 * ,在不同参数下,通过调用指针f就表现出不同的行为。一些说明:
 * 为什么定义函数指针f?函数指针可以指向参数和返回值都相同的,但实现不
 * 同的函数,因此,通过指针f调用函数时,就可以表现出不同的行为。
 * 为什么使用静态函数?因为函数指针不能指向非静态成员函数,编译器会报错。
 */

#ifndef MY_ARRAY_H
#define MY_ARRAY_H

#include <vector>
#include <stdexcept>
#include <mutex>

template<typename T>
class Array {
public:
    /**
     * 构造函数,根据参数的不同使函数指针指向不同的友元函数
     * @param singleThread true时指向单线程版本,为false时指向多线程版本
     */
    explicit Array(bool singleThread){
        if(singleThread) {//使函数指针指向单线程版本的函数
            push_agent = Array<T>::push_s;
            ptr_agent = Array<T>::ptr_s;
            get_agent = Array<T>::get_s;
            set_agent = Array<T>::set_s;
        } else{//使函数指针指向多线程版本的函数
            push_agent =  Array<T>::push_m;
            ptr_agent = Array<T>::ptr_m;
            get_agent = Array<T>::get_m;
            set_agent = Array<T>::set_m;
        }
    }
    virtual ~Array() {
        clear();
    }

    /**
     * 向函数末尾添加数据
     * @param elem 数据
     */
    inline void push(T &elem){
        push_agent(this,elem);//通过函数指针来调用函数,对外的接口是统一的
    }

    /**
     * 获取第index个元素的指针
     * @param index 索引
     * @return 指针
     */
    inline T* ptr(std::size_t index) {
        return ptr_agent(this,index);
    }

    /**
     * 获取第index个元素
     * @param index 索引
     * @return 元素
     */
    inline T get(std::size_t index) {
        return get_agent(this,index);
    }

    /**
     * elem更新第index个元素
     * @param index 索引
     * @param elem 元素
     */
    inline void set(std::size_t index, T elem) {
        set_agent(this,index,elem);
    }

    /**
     * 清空所有元素,并释放内存
     */
    inline void clear() {
        for (std::size_t i = 0; i < _pointer_vector.size(); i++) {
            delete _pointer_vector[i];
        }
        _pointer_vector.clear();
        _mutex.unlock();
    }

    /**
     * 返回元素个数
     * @return 大于等于0的数
     */
    inline size_t size() {
        std::lock_guard<std::mutex> lock(_mutex);
        return _pointer_vector.size();
    }

private:
    //这部分是函数指针的定义
    void (*push_agent)(Array<T> *me, T& elem);
    T* (*ptr_agent)(Array<T> *me,std::size_t index);
    T (*get_agent)(Array<T> *me,std::size_t index);
    void (*set_agent)(Array<T> *me,std::size_t index, T elem);
private:
    //这部分是单线程版本(_s,single)和多线程版本(_m,multi)静态函数的声明
    static void push_s(Array<T> *me, T& elem);
    static void push_m(Array<T> *me, T& elem);
    static T* ptr_s(Array<T> *me,std::size_t index);
    static T* ptr_m(Array<T> *me,std::size_t index);
    static T get_s(Array<T> *me,std::size_t index);
    static T get_m(Array<T> *me,std::size_t index);
    static void set_s(Array<T> *me,std::size_t index,T elem);
    static void set_m(Array<T> *me,std::size_t index,T elem);
private:
    std::vector<T *> _pointer_vector;
    std::mutex _mutex;
};


template <typename T>
void Array<T>::push_s(Array<T> *me, T &elem){
    auto node = new T;  //分配空间
    (*node) = elem;     //赋值
    me->_pointer_vector.push_back(node);//存下指针
}

template <typename T>
void Array<T>::push_m(Array<T> *me, T &elem) {
    auto node = new T;  //分配空间
    (*node) = elem;     //赋值
    std::lock_guard<std::mutex> lock(me->_mutex);   //加锁
    me->_pointer_vector.push_back(node);            //存下指针
}

template <typename T>
T* Array<T>::ptr_s(Array<T> *me, std::size_t index) {
    if (index < me->_pointer_vector.size()) {
        return me->_pointer_vector[index];
    } else {
        me->clear();//释放内存
        throw std::out_of_range("Array::ptr():index超出范围");
    }
}

template <typename T>
T* Array<T>::ptr_m(Array<T> *me, std::size_t index) {
    std::lock_guard<std::mutex> lock(me->_mutex);//加锁
    return ptr_s(me,index);//调用单线程的程序
}

template <typename T>
T Array<T>::get_s(Array<T> *me, std::size_t index) {
    if (index < me->_pointer_vector.size()) {
        return *(me->_pointer_vector[index]);
    } else {
        me->clear();//释放内存
        throw std::out_of_range("Array::ptr():index超出范围");
    }
}

template <typename T>
T Array<T>::get_m(Array<T> *me, std::size_t index) {
    std::lock_guard<std::mutex> lock(me->_mutex);
    return get_s(me,index);
}

template <typename T>
void Array<T>::set_s(Array<T> *me, std::size_t index,T elem) {
    *(ptr_s(me,index))=elem;
}

template <typename T>
void Array<T>::set_m(Array<T> *me, std::size_t index,T elem) {
    *ptr_m(me,index)=elem;
}


#endif //MY_ARRAY_H
 

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/DumpDoctorWang/article/details/79972855

C++ ---------------- 成员函数指针揭秘

1 前言 2 语法 3 与其它语言机制的混合使用 3.1 继承 3.2 虚函数 3.2 多继承 4 实现 4.1 Microsoft的实现 4.1.1 内部表示 4.1.2 Vcal...
  • ym19860303
  • ym19860303
  • 2013-02-18 10:32:52
  • 1870

类的非静态成员函数指针详解

From:http://blog.csdn.net/hairetz/archive/2009/05/06/4153252.aspx 个人感觉对于类的成员函数指针这块讲解的比较深入详细 推荐阅读 ///...
  • fuyunzhishang1
  • fuyunzhishang1
  • 2015-09-11 14:02:15
  • 933

C++中类成员函数指针的继承

C++中的成员函数指针(member function pointer)提供了对类成员函数进行动态访问的机制。比如定义如下的类: class Base { public:      void base...
  • socrates
  • socrates
  • 2007-12-26 15:13:00
  • 1462

通过函数指针调用C++非静态成员函数

  • 2008年04月24日 11:26
  • 1KB
  • 下载

C++成员变量指针和成员函数指针

深度探索C++对象模型这本书还有提到C++类的成员变量指针和成员函数指针,虽然在实际开发中用的不多,但是还是需要理解下。一:成员变量指针1.1 非静态成员指针类成员变量指针,实际上并不是真正意义上的指...
  • LaoJiu_
  • LaoJiu_
  • 2017-04-01 18:00:55
  • 1325

C++如何声明类成员函数指针或类成员变量指针(A::*)

例如有如下类,class A { int mem; int* func(void) { //... } };怎么声明类A的成员函数指针或成员变量指针呢?...
  • yockie
  • yockie
  • 2016-06-30 01:23:34
  • 2679

C++类的成员函数指针与普通的函数指针用法

1.类成员函数指针调用           注意:如果在类内调用,则函数指针声明要放在类里面.如果是类外调用,则函数指针声明放在调用类中. CFunCall.h文件: class CFunCall...
  • lyz769109884
  • lyz769109884
  • 2016-10-28 15:54:27
  • 2428

C++类 给结构体成员 函数指针 赋值

myStruct头文件 myStruct.h class CMyClass; struct {  int nFlag;  void (CMyClass::*myinit)(int n);...
  • u011526858
  • u011526858
  • 2016-02-07 15:30:07
  • 1253

C++关于类成员函数指针的正确写法

关于类成员函数指针的正确写法 10-09 Web开发 Dante 10,735 一般来说,函数指针的用法是比较简单的。 比如对于函数: int innerFunc(i...
  • a511244213
  • a511244213
  • 2015-05-26 16:02:52
  • 1456

C++获取类中成员函数的函数指针

注意调用类中非静态成员函数的时候,使用的是类名::函数名;而不是实例名::函数名。...
  • tingzhushaohua
  • tingzhushaohua
  • 2017-08-01 11:02:43
  • 2145
收藏助手
不良信息举报
您举报文章:C++类的函数指针成员
举报原因:
原因补充:

(最多只允许输入30个字)