[Linux]C++学习笔记(七)

函数指针,就是指向函数的指针。在C++中,函数指针一般是指全局命名空间中的函数指针,它与类成员函数指针有一点不同。

在类中,首先类是具有类域的。一个指向类的成员函数的指针,不同于函数指针,只是声明的形式不同,基本思想还是一致的。使用这些指针对操作可能会带来很大的方便。

另外,对于静态类来说,静态类没有this指针,静态类成员函数指针是普通函数指针,因为静态类成员函数是属于类的全局函数。

函数指针

先看一下函数指针的定义及其使用。

函数指针的定义需要指明函数返回类型、函数参数列表,这样才能使一个函数指针指向正确的函数,例如,定义一个返回值为void、没有参数列表的函数指针变量function_pointer,并对其初始化,初始化内容是函数void set_student_count():

         void (*function_pointer)() = set_student_count;

如果另一个函数void set_car_number()也是返回值为void、参数列表为空,可将该函数初始化给函数指针变量function_pointer,如下所示:

        function_pointer = set_car_number;

函数的参数列表不为空的话,也是一样的,要在声明一个函数指针的时候指明包含的函数参数列表内容(参数类型),例如,函数返回类型为void、参数列表为(string& , int),比如函数void get_from_first(string& s, int count) ,指向该函数的指针变量my_function_pointer可以声明并初始化为:

         void (*my_function_pointer)(string& , int) = get_from_first;

对于函数参数列表很长的函数,如果声明一个函数指针类型变量,显得很长,可以使用typedef来重定义函数指针类型,例如对上面的函数指针类型变量void (*my_function_pointer)(string& , int),可以重定义为:

         typedef void (*FP)(string&, int);

这里,FP就是指向返回类型为void、参数列表为(string& , int)的函数指针类型。接着,定义一个函数指针类型的变量,并初始化其值为函数get_from_first,如下所示:

        FP fp = get_from_first;

下面,写了两个函数get_from_first与get_from_last,分别从一个字符串的头部、尾部截取指定长度的字符串。通过定义函数指针FP指向这两个函数,将几个这两个函数的指针变量放入到容器vector中,然后迭代vector,使用迭代出来的函数对一个初始字符串进行操作。

代码实现如下所示:

#include <iostream>
#include <vector>
#include <string>

using namespace std;

typedef void (*FP)(string&, int); // 重定义函数指针类型

void print_message(int, const char*, string&);

inline void get_from_first(string& s, int count) {      s = s.substr(0, count); }
inline void get_from_last(string& s, int count) {       s = s.substr(s.size()-count); }

void print(int count, FP fp, string& after_s) {
        if(fp == get_from_first) {
                print_message(count, "get_from_first", after_s);
        }
        if(fp == get_from_last) {
                print_message(count, "get_from_last", after_s);
        }
}

void print_message(int count, const char *fname, string& after_s) {
        cout<<"Recall function "<<fname<<"\t[count="<<count<<"]\t:\t"<<after_s<<endl;
}

int main() {
        string s = "abcedfghijklmnopqrstuvwxyz9876543210";

        vector<FP> fp_vector;
        FP pf1 = get_from_first;
        fp_vector.push_back(pf1);
        FP pf2 = get_from_first;
        fp_vector.push_back(pf2);
        FP pl1 = get_from_last;
        fp_vector.push_back(pl1);
        FP pl2 = get_from_last;
        fp_vector.push_back(pl2);
        FP pl3 = get_from_last;
        fp_vector.push_back(pl3);

        int count_array[] = {   30, 25, 15, 8, 1        };
        for(int i=0; i<5; i++) {
                FP fp = fp_vector.at(i);
                fp(s, count_array[i]);
                print(count_array[i], fp, s);
        }
        return 0;
}

编译运行,结果如下所示:

Recall function get_from_first [count=30]      :       abcedfghijklmnopqrstuvwxyz9876
Recall function get_from_first [count=25]      :       abcedfghijklmnopqrstuvwxy
Recall function get_from_last   [count=15]      :       klmnopqrstuvwxy
Recall function get_from_last   [count=8]       :       rstuvwxy
Recall function get_from_last   [count=1]       :       y

类成员函数指针

类成员函数指针,与函数指针不同的是,类具有类域操作符,在声明类成员函数指针的时候,要指定成员函数返回值类型、类域操作符、成员函数参数列表,例如,对于一个已经存在的类TruncateString来说,它有成员函数void get_from_first(string& s, int count);,声明指向类TruncateString的成员函数指针,可以声明并初始化为如下形式:

        void (TruncateString::*tsfpf)(string&, int) = &TruncateString::get_from_first;

其中, void (TruncateString::*tsfpf)(string&, int)是声明指向TruncateString类成员函数,tsfpf是一个指向TruncateString类成员函数的指针变量,初始化的值&TruncateString::get_from_first表示是类TruncateString的成员函数void get_from_first(string& s, int count)。

说明一点,如何取得一个类成员函数指针变量的值的问题,也就是以怎样的形式为一个类的成员函数指针变量赋值,或者要进行比较,需要使用“引用操作符&、类域作用符、类成员函数”顺序连接的方式来获取到,例如上面例子中的&TruncateString::get_from_first,其中第三个部分只需要指定类成员函数的名称即可,不需要指明类成员函数的参数列表。

可以看出,“指向TruncateString类成员函数指针类型”这个类型很长,可以使用typedef重新定义类型,如下所示:

typedef void (TruncateString::*TSFP)(string&, int);

上面的TSFP,就是指向TruncateString类成员函数指针类型,它等价于上面的void (TruncateString::*)(string&, int),直接使用TSFP就能方便地声明指向TruncateString类成员函数的指针变量。

下面,将前面基于过程的函数指针的例子,转换成一个类TruncateString,从而方便灵活地使用类成员函数指针,TruncateString类定义在TruncateString.h头文件中,如下所示:

#include <iostream>
#include <vector>
#include <string>

using namespace std;

class TruncateString;
typedef void (TruncateString::*TSFP)(string&, int); // 重定义指向该类的成员函数的指针类型

class TruncateString {
        public:
                inline void get_from_first(string& s, int count) {      s = s.substr(0, count); }
                inline void get_from_last(string& s, int count) {       s = s.substr(s.size()-count);   }
                void print(int count, const TSFP tsfp, string& after_s);
        private:
                void print_message(int count, const char *fname, string& after_s);
};

TruncateString类中没有定义数据成员。接着,TruncateString类的成员函数实现在TruncateString.cpp文件中,如下所示:

#include "TruncateString.h"

void TruncateString::print(int count, const TSFP tsfp, string& after_s) {
        if(tsfp == &TruncateString::get_from_first) {
                print_message(count, "TruncateString::get_from_first", after_s);
        }
        if(tsfp == &TruncateString::get_from_last) {
                print_message(count, "TruncateString::get_from_last", after_s);
        }
}

void TruncateString::print_message(int count, const char *fname, string& after_s) {
        cout<<"Recall function "<<fname<<"\t[count="<<count<<"]\t:\t"<<after_s<<endl;
}

类TruncateString的实现中,通过成员函数指针变量调用成员函数执行,在这里实现了对调用成员函数执行情况进行打印输出信息的,因为在TruncateString类的头文件TruncateString.h中定义并实现了内联成员函数:inline void get_from_first(string& s, int count)与inline void get_from_last(string& s, int count)。

比较关键而且重要的是,如果调用类成员函数指针所指向的成员函数,通过实现一个测试用例类TruncateStringTest.cpp,来学习如何使用类成员函数指针变量:

#include <vector>
#include "TruncateString.h"

int main() {

        string s = "abcedfghijklmnopqrstuvwxyz9876543210";
        TruncateString *pts = new TruncateString;

        vector<TSFP> tsfp_vector;
        TSFP tsfpf1 = &TruncateString::get_from_first;
        tsfp_vector.push_back(tsfpf1);
        TSFP tsfpf2 = &TruncateString::get_from_first;
        tsfp_vector.push_back(tsfpf2);
        TSFP tsfpl1 = &TruncateString::get_from_last;
        tsfp_vector.push_back(tsfpl1);
        TSFP tsfpl2 = &TruncateString::get_from_last;
        tsfp_vector.push_back(tsfpl2);
        TSFP tsfpl3 = &TruncateString::get_from_last;
        tsfp_vector.push_back(tsfpl3);

        int count_array[] = {   30, 25, 15, 8, 1        };
        for(int i=0; i<5; i++) {
                TSFP tsfp = tsfp_vector.at(i);
                (pts->*tsfp)(s, count_array[i]);
                pts->print(count_array[i], tsfp, s);
        }
        delete pts;

        return 0;
}

上面对字符串"abcedfghijklmnopqrstuvwxyz9876543210",通过类TruncateString的提供的操作来处理。同样,定义了使用vector<TSFP>容器来存放指向TruncateString类的成员函数指针变量,从而迭代vector<TSFP>容器,连续使用vector<TSFP>容器中的类成员方法,对给定的字符串进行处理。

因为声明TruncateString *pts类指针变量,所以从vector<TSFP>容器中迭代出一个TSFP变量后,需要按照如下方式,将数据传入,调用成员函数处理:

                (pts->*tsfp)(s, count_array[i]);

其实,很好理解,根据括号“()”内的运算顺序,首先从左侧:通过*tsfp获取类的成员函数,再通过类指针变量pts通过指针运算符“->”来调用成员函数*tsfp,接着后面的括号中指定实参,就能够运算了。

如果定义一个类的变量:

                TruncateString ts;

实现上述功能的等价调用形式如下所示:

                (pts.*sfp)(s, count_array[i]);

就是将指针运算符“->”改成了“.”运算符,容易理解。

对测试用例类进行编译,运行输出测试结果如下所示:

[root@bogon pointer]# g++ -o TruncateString Trun*.cpp
[root@bogon pointer]# ./TruncateString
Recall function TruncateString::get_from_first [count=30]      :       abcedfghijklmnopqrstuvwxyz9876
Recall function TruncateString::get_from_first [count=25]      :       abcedfghijklmnopqrstuvwxy
Recall function TruncateString::get_from_last   [count=15]      :       klmnopqrstuvwxy
Recall function TruncateString::get_from_last   [count=8]       :       rstuvwxy
Recall function TruncateString::get_from_last   [count=1]       :       y

可见,同前面的函数指针中的测试程序的功能是相同的。

静态类的静态成员函数指针

静态类静态成员函数指针与普通函数指针的声明是相同的,不同的对于静态类的静态成员函数指针变量进行赋值时,应该在静态类的静态成员函数名称前面加上静态类类域作用符。

例如TruncateString是一个静态类,它有一个静态成员函数static void get_from_last(string& s, int count);,那么,声明指向静态类TruncateString的静态成员函数指针变量,并进行初始化,形式如下:

        void (*static_tspf)(string&, int) = &TruncateString::get_from_last;

其中static_tspf就是指向静态类TruncateString的静态成员函数的指针变量。使用指向静态类静态成员函数指针变量,对应于上面使用的例子,调用方式形如:

                tsfp(s, count_array[i]); // tsfp是指向静态类TruncateString的静态成员函数的指针变量
                TruncateString::print(count_array[i], tsfp, s); // 通过类域作用符调用静态类的静态成员函数

其实,在了解了函数指针和非静态类成员函数指针以后,对于静态类的成员函数指针变量的使用,应该很容易就能理解。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值