C ++获取指向受保护的覆盖函数的指针

时间:2016-06-03 21:17:30

标签: c++ inheritance member-function-pointers

为什么你不能在派生类中获得指向override方法的指针?

以下是一个例子:

基类

#ifndef BASE_H
#define BASE_H

class Base 
{

    typedef void (Base::*BasePointer)( void );

public:
    Base(){}

protected:

    virtual void FunFunction( void )
    {

    }

    BasePointer pointer;
};  

#endif  /* BASE_H */

派生类

#ifndef DERIVED_H
#define DERIVED_H

#include "Base.h"

class Derived : public Base
{
public:
    Derived()
    {
        pointer = &Base::FunFunction;

    }

protected:
    // Overrides base function
    void FunFunction( void )
    {

    }
};

#endif  /* DERIVED_H */

Derived类中的构造函数尝试将继承的指针值设置为等于覆盖方法FunFunction的地址。但产生的错误是"错误:' FunFunction'是' Base'"的受保护成员。更改FunFunction对公共的访问权限可以解决此问题。然而FunFucntion不能公开。

  1. 为什么FunFunction受保护会出现问题?

  2. 有什么方法可以获得这种理想的功能吗?

  3. 修改 解决方案是否可以将this转换为Base类,然后获取函数的地址?像&(((Base*)this)::FunFunction);之类的东西虽然那个例子不起作用。

2 个答案:

答案 0 :(得分:0)

您只能通过Base访问Derived受保护的成员。

至少在VS2012中从&Derived::Base::FunFunction yilds调用Derived没有错误。所以下面的代码将起作用:

class Base 
{
public:
    typedef void (Base::*BasePointer)( void );


    Base()
    {
        pointer2 = &Base::FunFunction;
    }

protected:

    virtual void FunFunction( void )
    {
        std::cout << "Base::FunFunction\n";
    }

    BasePointer pointer;
    BasePointer pointer2;
};  

class Derived : public Base
{
public:
    Derived()
    {
        pointer = &Derived::Base::FunFunction;
    }

    void RunBaseHiddenMethod()
    {       
        (this->*(pointer))();
    }

    void RunFunFunction()
    {
        FunFunction();
    }
protected:
    // Overrides base function
    virtual void FunFunction( void ) override
    {
        std::cout << "Derived::FunFunction\n";
    }
};

int main (int argc, char *argv[]) 
{
    Derived d;
    d.RunBaseHiddenMethod();
    d.RunFunFunction();
    return 0;
}

结果:

Derived::FunFunction
Derived::FunFunction

编辑:但是(正如你所看到的)它对你没有帮助! 在调试器中:

  

((Base )(&amp;(d))))。指针0x00be14ab {ConsoleApplication1.exe![thunk]:Base ::`vcall&#39; {0,{flat} }&#39; }&#39;}

     

((Base )(&amp;(d))))。pointer2 0x00be14ab {ConsoleApplication1.exe![thunk]:Base ::`vcall&#39; {0,{flat} }&#39; }&#39;}

指针只保存index virtual函数 - 而不是绝对地址。因此pointer==pointer2

BTW can访问static protected成员函数:

class Base 
{
public:
    typedef void (BasePointer)(void );
    Base(){}

protected:
    static void FunFunction( void )
    {
        std::cout << "Base::FunFunction\n";
    }

    BasePointer* pointer;
};  

class Derived : public Base
{
public:
    Derived()
    {
        pointer = &Base::FunFunction; //OK
    }

    void RunBaseMethod()
    {       
        pointer();
    }
};

另一个问题:为什么我们无法获得成员函数的绝对地址(如exported地址)?很明显,编译器知道这些地址。

答案 1 :(得分:-1)

Pure C ++不允许创建指向类的成员函数的指针,除非它是静态函数。 除非您使用的是C ++ Builder,它使用Delphi的技巧来创建和管理函数指针,否则您尝试做的事情是不可能的。请记住,类的成员函数具有指向类实例的隐藏参数。

萨姆