是否可以在运行时访问函数的v-table?可以确定元信息,例如不同功能版本的数量吗?这可能更像是一个理论问题,但是开发人员是否可以通过确保v-table永远不会超过一定数量的行来限制可以扩展给定基类的类的数量?
答案 0 :(得分:12)
是否可以在运行时访问函数的v-table?可以确定元信息,例如不同功能版本的数量吗?
不是以便携方式。该标准甚至没有虚拟表的概念,它更像是一个实现细节而不是一个需求,即使我知道的所有实现都使用vtable。在一般情况下,在运行时甚至没有足够的信息可用(即编译器不需要在vtable中存储条目数,因为它看到类型并且可以计数)
开发人员是否可以通过确保v-table永远不会超过一定数量的行来限制可以扩展给定基类的类的数量?
再次没有,但由于这表明存在误解,因此可能值得将它区分开来。当基类具有任何虚函数时,编译器(在所有使用vtable的实现中)将创建vtable,并且该表在基类中每个虚函数只有1个条目(加上一些额外的数据 - -typeinfo或指向它的指针,偏移到对象的开头或其他实现细节)。当类扩展该基类时,它不会向该vtable添加新元素,而是创建单独的vtable(或更多,取决于类型层次结构)。如果派生函数不添加任何新的虚函数,则派生对象的vtable将包含原始vtable具有的确切元素数。也就是说,您可以拥有庞大的继承层次结构,而不会影响vtable布局。将更改的是存储的typeinfo
数据和指向每个虚函数的指针,这些指针将引用最终覆盖
答案 1 :(得分:3)
确定不同功能版本数量等元信息?
没有C ++不支持reflection。您在C ++ AFAIK中无法实现的目标
答案 2 :(得分:1)
理论上,是的,因为它存储在内存中,您可以访问它。在实践中,没有合理的,可移植的方法,因为编译器可以以任何方式自由地实现虚函数,因此您必须深入了解编译器的源代码以找出访问所需的方式/位置信息以及如何解释它。
答案 3 :(得分:0)
您可以使用Debug Interface Access SDK或其他调试支持接口(gdb)进行此类操作。
RTT数据更具可移植性,但可能没有足够的项目详细信息。
有关限制v-table并防止其扩展太远的具体问题,您可以尝试this method;
<强> IDiaSymbol :: get_classParente 强> 检索对符号的类父级的引用。
HRESULT get_classParent (IDiaSymbol** pRetVal);
您可以调查所有与类相关的符号类型here,您可能想要做的是枚举加载的所有类类型,递归get_classParent并保留扩展基数的所有类的计数。
您的课程还可能要求在启动时提供符号以帮助执行。
答案 4 :(得分:0)
我能为你的努力想象的唯一一线希望就是处理dynamic_cast。每个编译器具有相应的库支持,具有遍历层次结构以实现动态转换的一些概念。如果你可以进入遍历,那么你可能会知道你正在处理多少级别的继承。也就是说,即使您完成了这项工作,它也将是特定于编译器的(正如其他人所说的那样),因为这种实现是专有的。