首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >检测C++虚拟函数是否已在派生类中重新定义的方法

检测C++虚拟函数是否已在派生类中重新定义的方法
EN

Stack Overflow用户
提问于 2011-01-19 21:58:15
回答 9查看 18.1K关注 0票数 43

简单地说:来自指向派生类实例的基类指针的,如何在运行时确定非纯虚拟函数(在基类中有实现)是否已在派生类中重新实现?

上下文:,我正在编写一个C++库来解决某些类的数学方程。库提供了一个包含多个虚拟函数的Equation类,库用户使用这些函数作为他们想要解决的特定方程的基类。库还提供了一个Solver类,它以一个Equation *作为构造函数参数。然后,用户按照以下代码编写代码:

代码语言:javascript
复制
class MyEquation : public Equation
{ ... } // equation definition here

int main()
{
  MyEquation myEqn;
  Solver solver(&myEqn);
  solver.Solve();
}

如果在导出的方程类中没有重新定义Equation中的某些虚拟函数组合,则可以省略由Solver对象运行的算法的某些计算开销较大的部分。因此,我想知道,在Solver的构造函数中,哪些函数已被重新定义,哪些函数将在Equation中运行默认实现。

  • --我希望这对库的用户来说是透明的,所以我不想寻找一个解决方案,例如,用户在导出的公式的构造函数中设置一些标志,指定哪些函数已被重新定义。
  • 一种可能的解决方案是,Equation中的虚拟函数的默认实现可以在Equation类中设置一个私有标志;然后,Solver类的构造函数可以清除此标志,运行虚拟函数,并检查标志值,以查看是否调用了Equation中的实现。不过,我想避免这种情况,因为每次执行虚拟函数时只需设置标志就可以大大降低算法的速度(这些虚拟函数的执行大大增加了程序的运行时间,默认实现只是返回一个常量)。
EN

回答 9

Stack Overflow用户

回答已采纳

发布于 2011-01-19 22:12:56

您无法检查是否可移植地覆盖虚拟函数。

您需要将知识带到Solver,最好是通过类型而不是运行时标志。

一种(基于类型的)方法是通过dynamic_cast检查是否存在一个接口。

一种可能更好的方法是提供解决方案函数的重载,在您的例子中是Solver构造函数。

如果您对问题提供了更具体的描述,可能会给出更好的建议。它确实提醒人们:(1)需要解决某些问题P;(2)设想技术方法X作为对P的解决方案;(3)发现X没有切割它;(4)询问如何使X对P进行模糊的描述,甚至对于一些无关的问题。原始问题P的细节通常会提出一个比X好得多的解决方案,而使X工作的问题与解决P无关。

票数 21
EN

Stack Overflow用户

发布于 2014-03-26 17:37:51

作为将来的参考,GCC提供了这个扩展:http://gcc.gnu.org/onlinedocs/gcc/Bound-member-functions.html,它允许检查一个方法是否被覆盖。

代码语言:javascript
复制
(void*)(obj.*(&Interface::method)) != (void*)(&Interface::method)

ICC正式支持这个扩展,clang的文档没有提到它,但是代码可以工作,甚至在没有警告的情况下编译。

不过,MSVC不支持这一点,所以确实如此。

此外,如果链接到实现已更改的库的不同版本,则似乎无法处理单独库中的标头(即内联)中定义的方法。如果我正确地解释了标准,这是未定义的行为(更改实现,即),但是如果实现保持不变,那么地址也应该是唯一的。所以不要用内联方法来做这件事。

票数 15
EN

Stack Overflow用户

发布于 2014-05-18 19:18:03

在只找到与gcc的PMF扩展相关的结果后,我认为必须有一个正确的方法。

我找到了一个没有任何黑客攻击的解决方案,并且至少在gcc &llvm身上进行了测试:

代码语言:javascript
复制
#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派生类,如果它重写事件方法,它将自动“链接”该事件。

票数 5
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/4741271

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档