在C ++中调用私有方法

时间:2011-07-29 12:33:31

标签: c++

这纯粹是一个理论问题,我知道如果有人声明私有方法,你可能不应该调用它。我设法调用私有虚方法并更改实例的私有成员,但我无法弄清楚如何调用私有非虚方法(不使用__asm)。有没有办法获得指向该方法的指针?还有其他方法吗?

编辑:我不想改变类定义!我只想要一个黑客/解决方法。 :)

11 个答案:

答案 0 :(得分:12)

my blog post。我在这里重新发布代码

template<typename Tag>
struct result {
  /* export it ... */
  typedef typename Tag::type type;
  static type ptr;
};

template<typename Tag>
typename result<Tag>::type result<Tag>::ptr;

template<typename Tag, typename Tag::type p>
struct rob : result<Tag> {
  /* fill it ... */
  struct filler {
    filler() { result<Tag>::ptr = p; }
  };
  static filler filler_obj;
};

template<typename Tag, typename Tag::type p>
typename rob<Tag, p>::filler rob<Tag, p>::filler_obj;

某些有私人成员的课程

struct A {
private:
  void f() {
    std::cout << "proof!" << std::endl;
  }
};

以及如何访问它们

struct Af { typedef void(A::*type)(); };
template class rob<Af, &A::f>;

int main() {
  A a;
  (a.*result<Af>::ptr)();
}

答案 1 :(得分:8)

#include头文件,但是:

#define private public
#define class struct

显然,您需要绕过各种包含警卫等,并在隔离的编译单元中执行此操作。

编辑: 仍然是hackish,但不那么:

#include <iostream>

#define private friend class Hack; private

class Foo
{
public:
    Foo(int v) : test_(v) {}
private:
    void bar();
    int test_;
};
#undef private
void Foo::bar() { std::cout << "hello: " << test_ << std::endl; }

class Hack
{
public:
    static void bar(Foo& f) {
        f.bar();
    }
};

int _tmain(int argc, _TCHAR* argv[])
{
    Foo f(42);
    Hack::bar(f);
    system("pause");
    return 0;
}

答案 2 :(得分:5)

如果public函数返回private函数的地址,则可以调用它,然后任何人都可以使用该地址来调用私有函数。

实施例,

class A
{
   void f() { cout << "private function gets called" << endl; }
 public:
     typedef void (A::*pF)();
     pF get() { return &A::f; }
};

int main() 
{
        A a;
        void (A::*pF)() = a.get();
        (a.*pF)(); //it invokes the private function!
}

输出:

private function gets called

在ideone演示:http://www.ideone.com/zkAw3

答案 3 :(得分:2)

您有friend个类和函数。

  

我知道如果有人声明私有方法,你可能会   不应该叫它。

重点不是'你不应该叫它',它只是'你不能称之为'。你究竟想做什么?

答案 4 :(得分:2)

最简单的方法:

#define private public
#define protected public

答案 5 :(得分:1)

从同一个类的公共函数调用私有方法。

答案 6 :(得分:1)

跟进T.E.D.的答案:不要编辑标题。而是创建自己的标头私有副本,并在标头的伪造副本中插入一些friend声明。在您的来源中,#include这个虚假的标题而不是真实的标题。瞧!

将private更改为public可能会更改内联方法导致的弱符号,这反过来可能会导致链接器抱怨。如果所做的只是添加一些朋友声明,那么内联方法产生的弱符号将与假冒和真实标题具有相同的签名。通过这些朋友声明,您现在可以使用类来执行各种恶意操作,例如访问私有数据和调用私有成员。

<强>附录
如果相关标头使用#pragma once而不是#include防护来确保标头是幂等的,则此方法无效。

答案 7 :(得分:0)

嗯,显而易见的方法是编辑代码,使其不再是私密的。

如果你坚持找到 evil 的方式来做...好吧......对于一些编译器,可能会创建你自己的头文件版本,其中一个方法是{{1而不是public。虽然邪恶有一种讨厌的反弹方式(这就是为什么我们称之为“邪恶”)。

答案 8 :(得分:0)

我认为你最接近hack is this,但这不仅是不明智的,而是未定义的行为所以它没有语义。如果碰巧以任何单个程序调用的方式运行,那那就是纯粹的机会。

答案 9 :(得分:0)

定义一个类似的类,除了公共函数之外,它是相同的。

然后使用私有函数对具有public函数的对象进行类型转换,然后可以调用public函数。

答案 10 :(得分:0)

如果我们谈到MSVC,我认为除了调用私有方法本身之外没有其他危害的最简单方法是伟大的__asm:

class A
{
private:
    void TestA () {};
};

A a;
__asm
{
    // MSVC assumes (this) to be in the ecx.
    // We cannot use mov since (a) is located on the stack
    // (i.e. [ebp + ...] or [esp - ...])
    lea     ecx, [a]
    call    A::TestA
}