访问同一类中的私有虚拟函数
Accessing private virtual functions within same class
我被要求使用此代码并只写入extractMultAdd()
函数,返回variable.x
variable.y
variable.add()
和variable.multiply
。我理解虚拟表的基本概念以及创建它们的时间,但尽管我尽了最大努力,我还是不太确定如何利用它们来访问私有虚拟功能。如有任何帮助,我们将不胜感激。
#include <cstdio>
#include <iostream>
class MultAdd
{
private:
int x;
int y;
virtual int add() //virtual fuction so vtable created for Thing class
{
return x+y;
}
virtual int multiply()
{
return x*y;
}
public:
MultAdd(){
x = 2;
y = 10;
}
};
int extractMultAdd(void* math)
{
return 0;
}
int main()
{
MultAdd variable;
printf("%dn", extractMultAdd(&variable));
return 0;
}
我给您两个版本供您选择。它们不遵循标准,也不可移植,但在我测试的时候,它们都适用于MSVC 2013、GCC 4.9和clang 3.5。第二个版本比第一个版本相对更安全、更可移植。事实上,我预计它会相当稳健。
版本1:
#include <iostream>
class MultAdd {
private:
int x;
int y;
virtual int add() { return x + y; }
virtual int multiply() { return x * y; }
public:
MultAdd() {
x = 2;
y = 10;
}
};
struct MultAddCracker: MultAdd {
int add();
int multiply();
};
void extractMultAdd(MultAdd& v) {
char* p = (char*)&v;
std::cout << *(int*)(p + sizeof(void*)) << 'n';
std::cout << *(int*)(p + sizeof(void*) + sizeof(int)) << 'n';
MultAddCracker* pcracker = (MultAddCracker*)&v;
std::cout << pcracker->add() << 'n';
std::cout << pcracker->multiply() << 'n';
}
int main() {
MultAdd v;
extractMultAdd(v);
}
版本2:
#include <iostream>
class MultAdd {
private:
int x;
int y;
virtual int add() { return x + y; }
virtual int multiply() { return x * y; }
public:
MultAdd() {
x = 2;
y = 10;
}
};
struct MultAddCracker {
int x;
int y;
virtual int add();
virtual int multiply();
};
void extractMultAdd(MultAdd& v) {
MultAddCracker& w = (MultAddCracker&)v;
std::cout << w.x << 'n';
std::cout << w.y << 'n';
std::cout << w.add() << 'n';
std::cout << w.multiply() << 'n';
}
int main() {
MultAdd v;
extractMultAdd(v);
}
如果您正在寻找一种可移植的方法,我可以提供以下内容,C++编译器必须支持这些内容。这里将进一步讨论。简言之,它利用了在14.7.2p8:的显式模板实例化中绕过访问检查规则的事实
14.7.2p8通常的访问检查规则不适用于用于指定显式实例化的名称。[注意:特别是,函数声明符中使用的模板参数和名称(包括参数类型、返回类型和异常规范)可能是通常不可访问的私有类型或对象,模板可能是通常无法访问的成员模板或成员函数。]
它几乎能做你想做的事情;唯一需要注意的是,根据14.2:,模板声明不能在函数范围内
模板声明只能作为命名空间或类作用域声明出现
这可能会破坏问题的精神,尽管它的措辞方式。我不知道有什么方法可以将模板结构隐藏到函数范围中,但如果有类似的技巧,这可以100%实现你想要的。
////////////////////////////////////////////////////////////////////////////////////////
//// The template classes can unfortunately not be declared inside extractMultAdd ()
////////////////////////////////////////////////////////////////////////////////////////
#define ROB_PRIVATE_MEMBER_INST(CLASS, TYPE, MEMBER)
template<typename T>
struct CLASS##_##MEMBER##_rob_tag {
typedef T CLASS::*type;
friend type get(CLASS##_##MEMBER##_rob_tag);
};
template<typename Tag, typename Tag::type M>
struct CLASS##_##MEMBER##_rob_private
{
friend typename Tag::type get(Tag) { return M; }
};
template struct CLASS##_##MEMBER##_rob_private<
CLASS##_##MEMBER##_rob_tag<TYPE> , &CLASS::MEMBER>;
#define ROB_PRIVATE_MEMBER_INST_FN(CLASS, TYPE, MEMBER)
template<typename T>
struct CLASS##_##MEMBER##_rob_tag {
typedef T type;
friend type get(CLASS##_##MEMBER##_rob_tag);
};
template<typename Tag, typename Tag::type M>
struct CLASS##_##MEMBER##_rob_private
{
friend typename Tag::type get(Tag) { return M; }
};
template struct CLASS##_##MEMBER##_rob_private<
CLASS##_##MEMBER##_rob_tag<TYPE> , &CLASS::MEMBER>;
#define ROB_PRIVATE_MEMBER_ACCESS(CLASS, INSTANCE, TYPE, MEMBER)
(INSTANCE.*get(CLASS##_##MEMBER##_rob_tag<TYPE>()))
////////////////////////////////////////////////////////////////////////////////////////
//// Actually use the macros
////////////////////////////////////////////////////////////////////////////////////////
ROB_PRIVATE_MEMBER_INST(MultAdd, int, x);
ROB_PRIVATE_MEMBER_INST(MultAdd, int, y);
ROB_PRIVATE_MEMBER_INST_FN(MultAdd, int(MultAdd::*)(), add);
ROB_PRIVATE_MEMBER_INST_FN(MultAdd, int(MultAdd::*)(), multiply);
////////////////////////////////////////////////////////////////////////////////////////
//ROB_PRIVATE_MEMBER_INST_FN(MultAdd, int(__thiscall *)(), add);
int extractMultAdd(void* math)
{
// No need to pass as void*
MultAdd *pMA(reinterpret_cast<MultAdd*>(math));
// ROB_PRIVATE_MEMBER_INST(MultAdd, int, x); // Note that unfortunately this isn't possible
// The 4 values, retrieved in a portable way
int robbed_x = ROB_PRIVATE_MEMBER_ACCESS(MultAdd, *pMA, int, x);
int robbed_y = ROB_PRIVATE_MEMBER_ACCESS(MultAdd, *pMA, int, y);
int robbed_add = ROB_PRIVATE_MEMBER_ACCESS(MultAdd, *pMA, int(MultAdd::*)(), add)(); // Note we're calling function with ()
int robbed_mul = ROB_PRIVATE_MEMBER_ACCESS(MultAdd, *pMA, int(MultAdd::*)(), multiply)(); // Note we're calling function with ()
return 0;
}
忽略好友声明警告并滚动到输出:
运行示例
当然,"只在extractResultAdd()函数中编写"可能会为这种语义欺骗留下一些空间:
int extractMultAdd(void* math)
{
return extractMultAdd_impl(math);
}
// structs
int extractMultAdd_impl(void* math)
{
// original code ...
} // <== Original brace :)
相关文章:
- C++无法定义虚拟函数 OUTER 类和头文件
- 用常见虚拟函数实现的任意组合来实现派生类的正确方法是什么
- 尝试将unique_ptrs推送到向量时使用纯虚拟函数错误
- 有没有比在库中添加一个并非由所有派生类实现的新虚拟函数更好的设计实践
- 类型擦除的std::function与虚拟函数调用的开销
- 重写虚拟函数和继承
- 用纯虚拟函数兜圈子
- 为什么使用存储在虚拟方法表中的地址调用虚拟函数的函数会返回垃圾?
- 禁止子函数调用父级的抽象(或虚拟)函数
- 无法在子类中使用虚拟函数C++
- 无法在派生对象上运行虚拟函数
- 我可以调用从 main() 覆盖的虚拟函数吗?
- 在 C++ 中将函数获取和设置为虚拟函数
- 使用在堆栈上创建的对象调用虚拟函数
- 为什么在这种情况下不调用我的虚拟函数实现?
- 在C++中使虚拟函数私有化
- 模板继承类中的虚拟函数
- 为什么构造函数的虚拟函数调用有时有效,但其他调用却无效
- doxygenc++虚拟函数和实现
- 如何从派生类函数中调用虚拟函数