zoukankan      html  css  js  c++  java
  • [转]使用成员函数指针的一些注意事项

    在C++编程中,成员函数指针并不常用,并且由于它实现比较复杂,很容易导致编程错误。

    基本用法:

    class B {
    public:
        int f(int a, int b) {
            return (a + b) * m_c;
        }

        int m_c;
    };

    int main() {

        typedef int (B::*MEM_FUNC)(int, int);  // 定义成员函数指针类型MEM_FUNC
        MEM_FUNC pmf;                          // 定义成员函数指针pmf
        pmf = NULL;  // 指针可以设置为NULL
        pmf = &B::f; // 指针可以指向一个成员函数

        B b1, b2;
        b1.m_c = 10;
        b2.m_c = 20;

        int i1 = (b1.*pmf)(30, 40); // 调用b1.f(30, 40)
        int i2 = (b2.*pmf)(50, 60); // 调用b2.f(50, 60)

        B* p = &b1;
        int i3 = (p->*pmf)(70, 80); // 调用b1.f(70, 80)

        return 0;
    }

    C++语言最初设计的时候,没有继承,没有虚函数,等等,所以成员函数指针的使用也并不复杂。但是随着多重继承、虚拟继承等特性被引入,成员函数指针开始变得复杂了。

    首先是大小的改变。虽然“成员函数指针”是一种指针,但它所占的空间却可能比一般指针要大。以VC为例(VC6至VC2010均如此),在单继承、多继承、虚拟继承的情况下,成员函数指针的大小分别为4字节、8字节、12字节。如果不知道一个类是否继承(此时这个类只有一份向前声明,而没有提供实际定义),则它的成员函数指针最多可以占据16个字节,大大的超过了一般指针的4字节。

    然后是类型转换问题。一般情况下,派生类的指针转化为基类的指针不会有任何问题(因为继承就意味着is a kind of)。但是,派生类的成员函数指针却不可以转化为基类的成员函数指针。示例代码:
    int main() {
        typedef void(std::istream::*PMF_B)(int);
        typedef void(std::ifstream::*PMF_D)(int);
        PMF_B b = 0;
        PMF_D d = 0;
        d = b; // 编译错误
        return 0;
    }
    为什么编译错误呢?从字节数来讲,因为派生类的成员函数指针,它的字节数可能比基类的成员函数指针更多。如果成功转换,则会导致字节数减少,某些有用的信息可能就丢失了。但更重要的原因是,派生类的成员函数指针可以指向派生类的函数,而派生类的这些函数可能是基类所没有的。此时,就算成功的完成转换,在运行之时也肯定导致内存错误。反过来,如果把基类的成员函数指针转换为派生类的成员函数指针,则是完全可以的。

    还有就是关于VC系列编译器,在一个问题上没有按照C++标准来处理。标准规定各种成员函数指针之间,可以用reinterpret_cast来完成强制转换,但VC系列编译器在实现这一点时有存在问题,可能导致编译错误。解决此问题的办法是用union hack,具体作法是定义一个union,其中包含了转换之前和转换之后的成员指针类型。然后设置/取值即可。

    最后,boost提供了一套mem_fn,它是std::mem_fun更加通用的版本(std::mem_fun只支持无参数、单参数版本,boost::mem_fn支持更多参数)。可以把对成员函数的调用转化为类似普通函数的形式。这一套mem_fn已经被纳入到TR1,在VC 2008 SP1和以上版本可以直接使用。

  • 相关阅读:
    无需认证的mail,适用于ZABBIX等运维系统
    Linux交换分区使用过多的处理办法
    zookeeper的单实例和伪集群部署
    Zookeeper分布式集群原理与功能
    Nginx禁止IP直接访问网站
    镜像站地址汇总
    Nginx反向代理后端多节点下故障节点的排除思路
    Redis主从复制与高可用方案
    http_proxy_module模块常用参数
    Nginx实现负载均衡的几种方式
  • 原文地址:https://www.cnblogs.com/wxxweb/p/2441755.html
Copyright © 2011-2022 走看看