简单地说:来自指向派生类实例的基类指针的,如何在运行时确定非纯虚拟函数(在基类中有实现)是否已在派生类中重新实现?
上下文:,我正在编写一个C++库来解决某些类的数学方程。库提供了一个包含多个虚拟函数的Equation类,库用户使用这些函数作为他们想要解决的特定方程的基类。库还提供了一个Solver类,它以一个Equation *作为构造函数参数。然后,用户按照以下代码编写代码:
class MyEquation : public Equation
{ ... } // equation definition here
int main()
{
MyEquation myEqn;
Solver solver(&myEqn);
solver.Solve();
}如果在导出的方程类中没有重新定义Equation中的某些虚拟函数组合,则可以省略由Solver对象运行的算法的某些计算开销较大的部分。因此,我想知道,在Solver的构造函数中,哪些函数已被重新定义,哪些函数将在Equation中运行默认实现。
Equation中的虚拟函数的默认实现可以在Equation类中设置一个私有标志;然后,Solver类的构造函数可以清除此标志,运行虚拟函数,并检查标志值,以查看是否调用了Equation中的实现。不过,我想避免这种情况,因为每次执行虚拟函数时只需设置标志就可以大大降低算法的速度(这些虚拟函数的执行大大增加了程序的运行时间,默认实现只是返回一个常量)。发布于 2011-01-19 22:12:56
您无法检查是否可移植地覆盖虚拟函数。
您需要将知识带到Solver,最好是通过类型而不是运行时标志。
一种(基于类型的)方法是通过dynamic_cast检查是否存在一个接口。
一种可能更好的方法是提供解决方案函数的重载,在您的例子中是Solver构造函数。
如果您对问题提供了更具体的描述,可能会给出更好的建议。它确实提醒人们:(1)需要解决某些问题P;(2)设想技术方法X作为对P的解决方案;(3)发现X没有切割它;(4)询问如何使X对P进行模糊的描述,甚至对于一些无关的问题。原始问题P的细节通常会提出一个比X好得多的解决方案,而使X工作的问题与解决P无关。
发布于 2014-03-26 17:37:51
作为将来的参考,GCC提供了这个扩展:http://gcc.gnu.org/onlinedocs/gcc/Bound-member-functions.html,它允许检查一个方法是否被覆盖。
(void*)(obj.*(&Interface::method)) != (void*)(&Interface::method)ICC正式支持这个扩展,clang的文档没有提到它,但是代码可以工作,甚至在没有警告的情况下编译。
不过,MSVC不支持这一点,所以确实如此。
此外,如果链接到实现已更改的库的不同版本,则似乎无法处理单独库中的标头(即内联)中定义的方法。如果我正确地解释了标准,这是未定义的行为(更改实现,即),但是如果实现保持不变,那么地址也应该是唯一的。所以不要用内联方法来做这件事。
发布于 2014-05-18 19:18:03
在只找到与gcc的PMF扩展相关的结果后,我认为必须有一个正确的方法。
我找到了一个没有任何黑客攻击的解决方案,并且至少在gcc &llvm身上进行了测试:
#include <iostream>
#include <typeinfo>
struct A { virtual void Foo() {} };
struct B : public A { void Foo() {} };
struct C : public A { };
int main() {
std::cout << int(typeid(&A::Foo) == typeid(&A::Foo)) << std::endl;
std::cout << int(typeid(&A::Foo) == typeid(&B::Foo)) << std::endl;
std::cout << int(typeid(&A::Foo) == typeid(&C::Foo)) << std::endl;
return 0;
}http://ideone.com/xcQOT6
PS:我实际上在CEventClient系统中使用它。因此,您从CEventClient派生类,如果它重写事件方法,它将自动“链接”该事件。
https://stackoverflow.com/questions/4741271
复制相似问题