【问题标题】:Able to use pointer to function to call private method of an external class能够使用指向函数的指针来调用外部类的私有方法
【发布时间】:2015-02-16 16:52:46
【问题描述】:

基于以下answer 到最近的question,我可以使用函数指针从另一个类Bar 调用私有方法Foo<T>::foo(),如下所示(另请参见@ 987654323@)

#include <iostream>

template<typename T>
struct Bar
{
    typedef void (T::*F)();

    Bar( T& t_ , F f ) : t( t_ ) , func( f )
    {
    }

    void operator()()
    {
        (t.*func)();
    }

    F func;
    T& t;
};

template<typename T>
class Foo
{
private:
    void foo()
    {
        std::cout << "Foo<T>::foo()" << std::endl;
    }

public:    
    Foo() : bar( *this , &Foo::foo ) 
    {
        bar();
    }

    Bar<Foo<T> > bar;
};

int main()
{
    Foo<int> foo;
}

这适用于 MSVC 2013 和 GCC 4.8.3。有效吗?

【问题讨论】:

  • 当然,为什么不应该呢?分配指针时检查访问权限。
  • 这和去public: void buz() { foo(); }真的没什么区别

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


【解决方案1】:

C++ 标准说

11.1 类的成员可以是
(1.1)——私有的;也就是说,它的名字只能被声明它的类的成员和朋友使用。

即访问说明符应用于名称,而不是可执行代码。如果您考虑一下,这是有道理的,因为访问说明符是编译时构造。

【讨论】:

  • 是的,标准报价。
  • 需要注意的是,类Foo选择为Bar的构造函数提供指向函数的指针。如果没有来自内部的帮助,Bar 将无法从外部呼叫Foo::foo()
【解决方案2】:

是的,这是允许的,并且有效。

C++ Programming by Bjarne Stroustoup

C++ 防止意外而不是故意规避 (欺诈)

当然,您不能直接/轻松地在类外调用私有方法,但如果您付出了足够的努力,C++ 将允许这样做。

【讨论】:

  • 这里不涉及规避,直接使用指针。
  • @Deduplicator 规避私有数据成员。
  • @Deduplicator (t.*func)(); -- 规避,私有成员 --> void foo()。我错过了什么?
  • @PranitKothari Foo 是形成一个指向其私有成员函数的指针,这显然是允许的。所有Bar&lt;Foo&lt;T&gt;&gt; 都知道它被传递了一个指向something 的成员函数的指针,此时访问控制并没有出现。您只是通过调用 Bar::operator() 来调用该 something
  • 是的,但它这样做只是因为它碰巧用指向私有成员函数的指针进行了初始化。 OP 似乎对访问控制的工作原理感到困惑,而您的回答暗示他正在偷偷摸摸地绕过访问控制,而实际上并没有发生这样的事情。
【解决方案3】:

是的,它是有效的。

Bar.operator()() 只是使用指针,而不是尝试使用带有私有访问说明符的标识符。
该指针是如何初始化的并不重要,只要它指向正确的函数即可。

As an example, look at this:

#include <iostream>
struct A {
protected:
    void hidden() { std::cout << "But I was hidden !?\n"; }
};
struct B : A {
    using A::hidden; // Making it public
};
int main() {
    B().hidden();
}

顺便说一句,除非你真的想刷新流,否则不要使用std::endl,因为这很昂贵。
通常'\n' 就足够了。

【讨论】:

    【解决方案4】:

    这很重要。

    头文件

    class A;
    typedef int (A::*handler)(int x);
    struct handler_pair {
        int code,
        handler fn
    }
    
    class A {
    ...
    private:
      int onGoober(int x);
      int onGomer(int x);
    };
    

    源文件

    handler_pair handler_map[] = {
        {0, &A::onGoober},          // these will complain about the method being private
        {1, &A::onGomer}
    };
    

    将 handler_map 更改为类中的静态成员并以这种方式初始化可以避免投诉。

    成员函数的地址取到哪里很重要。

    【讨论】:

      猜你喜欢
      • 2020-09-02
      • 1970-01-01
      • 2022-01-15
      • 1970-01-01
      • 2021-11-30
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多