我知道我可以创建方法指针,而且我知道它们通常不同于函数指针。不允许在它们之间转换。方法指针可以包含大量关于如何调整this
指针等的数据。
我想知道如何获取正在执行给定方法的代码的实际地址。此地址不会以任何方式被引用,但将用作给定方法所属类型的标识符 - 有点像 RTTI,优点是对库边界不敏感,因为此代码通常仅在一个单元中可用.
编辑:
为什么我不添加一些getType()
返回对象类型的方法?
因为我希望能够以这种方式使用不仅是我创建的类。我想要做的基本上是我的variant
类的实现,它基本上可以接受所有东西,只要存在给定类型的 void* getVariantId() 特化。
那么我可以写:
template <typename T>
class getTypeId{
};
class foo{
public:
void bar();
};
// getTypeId declared but not defined for generic type T earlier...
template <>
class getTypeId<foo>{
static void* get<foo>(){
return &foo::bar;
}
};
void doSomething(myVariant var);
int main(int argc, char* argv[]){
foo f;
myVariant var = myVariant::fromType<foo*>(&f);
doSomething(f);
}
void doSomething(myVariant var){
foo* f = var.toType<foo*>(); // Returns foo object from main
int* i = var.toType<int*>(); // returns null, as var is not int* in my example.
}
这个想法是fromType
用于getTypeId
获取类型的表示值,并将其与对象的指针一起转换为void*
. toType
另一方面,比较从 `getTypeId::get 获得的值和存储在对象中的值 - 如果匹配,则将内部保存的对象指针重新解释回原始类型并返回。
这个解决方案的美妙之处在于,即使有一些定义类型 x 的共享库 X,然后是分别使用库 X 的库 Y 和 Z,也会同意类型 x 是相同的(例如,如果在 Y 中创建的变体是传递给 Z),导致 X::method 上的地址保持不变。作为 Y 或 Z 库的创建者(但不是 X !!!),我不需要确保 X 库启用了 RTTI,甚至不需要知道 myVariant 的存在,但类型 x 仍然完全兼容 myVariant。
编辑2:
我现在看到没有独立于实现的方法来完成这项工作。但是,我认为这是不通常需要的怪癖,因此不存在的功能,而不是不可能创建的功能。我想我仍然没有明确我想要实现什么以及我打算如何做到这一点。所以:
这里的库是指共享库(.dll、.so 等)。
每个不是纯虚拟的方法(意味着定义的每个方法)都必须有实现。此实现的行为类似于接受一个附加参数的函数
this
- 虚函数仅在调用方方面有所不同。让我们以类 X 及其方法X::foo
为例。该方法只绑定到 X 类型,即使 Y 类型继承了它,该方法仍然存在X::foo
,因此足以识别 typeX
。在子类中覆盖虚拟方法或覆盖方法Xchild
实际上是用新地址定义新方法 Xchild::foo。那么你可能会使用Xchild::foo
to 来表示Xchild
,但不是X
。如果类型 X(准确地说是所有方法)在库 libX 中定义,并且 libY 和 libZ 都在使用 libX(但彼此不知道),并且出于自己的目的定义 getTypeId 使用 X 中的第一种方法来表示它(请注意,这不会对 libX 开发人员强加任何东西),那么他们就 X 是什么类型达成了一致。如果应用程序开发人员使用 libY 获取变体并将其传递给 libZ,则两者都将正确识别提到的类型。
我不是在尝试开发类型转换变量 - 保存为 X 的变量只能读取为 X,即使传递给 myVariant 的实际指针是 Xchild。我对获取给定实例的最顶层类的类型不感兴趣 - 只是用于创建变体的类。