提问人:Luchian Grigore 提问时间:7/29/2011 最后编辑:CactusLuchian Grigore 更新时间:2/18/2023 访问量:46126
在 C++ 中调用私有方法
Calling private method in C++
问:
这纯粹是一个理论问题,我知道如果有人声明一个方法私有,你可能不应该调用它。我设法调用了私有虚拟方法并更改了实例的私有成员,但我无法弄清楚如何调用私有非虚拟方法(不使用 )。有没有办法获取指向该方法的指针?还有其他方法可以做到吗?__asm
编辑:我不想更改类定义!我只想要一个黑客/解决方法。:)
答:
#include
头文件,但是:
#define private public
#define class struct
显然,您需要绕过各种包含保护等,并在一个隔离的编译单元中执行此操作。
编辑: 仍然很骇人听闻,但不那么骇人听闻:
#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;
}
评论
class A { void f() {} };
friend
从同一类的公共函数调用私有方法。
好吧,显而易见的方法是编辑代码,使其不再是私有的。
如果你坚持要找一个邪恶的方法来做这件事......井。。。对于某些编译器,它可能会创建您自己的头文件版本,其中一种方法是 而不是 .不过,邪恶有一种令人讨厌的方式反弹到你身上(这就是为什么我们称之为“邪恶”)。public
private
评论
如果函数返回函数的地址,则可以调用它,然后任何人都可以使用该地址调用私有函数。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
评论
你有朋友类和函数。
我知道,如果有人将某个方法声明为私有,您可能会 不应该叫它。
重点不是“你不应该叫它”,而只是“你不能叫它”。你到底想做什么?
评论
最简单的方法:
#define private public
#define protected public
评论
T.E.D.的回答:不要编辑标题。相反,创建您自己的标头的私有副本,并在标头的虚假副本中插入一些声明。在您的来源中,这个虚假的标题而不是真实的标题。瞧!friend
#include
将 private 更改为 public 可能会更改内联方法产生的弱符号,这反过来又可能导致链接器抱怨。如果所做的只是添加一些友元声明,则由内联方法生成的弱符号将具有与虚假和真实标头相同的签名。通过这些好友声明,您现在可以对类执行各种邪恶的事情,例如访问私有数据和调用私有成员。
附录:如果有问题的标头使用而不是守卫来确保标头是幂等的,
则此方法将不起作用。#pragma once
#include
我认为你最接近黑客攻击的是这个,但它不仅是不明智的,而且是未定义的行为,所以它没有语义。如果它碰巧按照您想要的方式运行任何单个程序调用,那么这纯粹是偶然的。
评论
#define
定义一个类似的类,除了函数是公共函数之外,该类是相同的。
然后,将具有私有函数的对象类型转换为具有公共函数的对象,然后可以调用公共函数。
请参阅我的博客文章。我在这里重新发布代码
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)();
}
评论
如果我们说的是 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
}
评论
对于 GCC,可以通过使用函数的残缺名称来完成。
#include <stdio.h>
class A {
public:
A() {
f(); //the function should be used somewhere to force gcc to generate it
}
private:
void f() { printf("\nf"); }
};
typedef void(A::*TF)();
union U {
TF f;
size_t i;
};
int main(/*int argc, char *argv[]*/) {
A a;
//a.f(); //error
U u;
//u.f = &A::f; //error
//load effective address of the function
asm("lea %0, _ZN1A1fEv"
: "=r" (u.i));
(a.*u.f)();
return 0;
}
损坏的名称可以通过 nm *.o 文件找到。
添加 -masm=intel 编译器选项
来源: GCC 错误: 无法将 offsetof 应用于成员函数 MyClass::MyFunction https://gcc.gnu.org/onlinedocs/gcc/Extended-Asm.html
调用私有方法的最简单方法(基于之前的答案,但更简单一些):
// Your class
class sample_class{
void private_method(){
std::cout << "Private method called" << std::endl;
}
};
// declare method's type
template<typename TClass>
using method_t = void (TClass::*)();
// helper structure to inject call() code
template<typename TClass, method_t<TClass> func>
struct caller{
friend void call(){
TClass obj;
(obj.*func)();
}
};
// even instantiation of the helper
template struct caller<sample_class,&sample_class::private_method>;
// declare caller
void call();
int main(){
call(); // and call!
return 0;
}
评论
在阅读了 寻找一种优雅且非侵入性的方式来访问类的私有方法之后,我想总结一种理想的方法,因为这里没有其他人粘贴过它:
// magic
//
template <typename Tag, typename Tag::pfn_t pfn>
struct tag_bind_pfn
{
// KEY: "friend" defines a "pfn_of" out of this template. And it's AMAZING constexpr!
friend constexpr typename Tag::pfn_t pfn_of(Tag) { return pfn; }
};
// usage
//
class A
{
int foo(int a) { return a; }
};
struct tag_A_foo
{
using pfn_t = int (A::*)(int);
// KEY: make compiler happy?
friend constexpr typename pfn_t pfn_of(tag_A_foo);
};
// KEY: It's legal to access private method pointer on explicit template instantiation
template struct tag_bind_pfn<tag_A_foo, &A::foo>;
inline static constexpr const auto c_pfn_A_foo = pfn_of(tag_A_foo{});
#include <cstdio>
int main()
{
A p;
auto ret = (p.*(c_pfn_A_foo))(1);
printf("%d\n", ret);
return 0;
}
上一个:四舍五入到最接近的数字的倍数
下一个:哪些特殊规则适用于一元和运算符?
评论