获取指向虚拟方法的指针
Obtain pointer to virtual method?
我有一个函数需要在循环中多次调用虚拟方法,并希望有一种方法可以避免每次都产生 vtable 查找的开销。我想也许获得指向该方法的指针会是解决此问题的好方法。下面的代码显示了我正在尝试做的事情,问题是 Derived
中方法的地址无法分配给 Base
成员函数指针。
class Base
{
public:
typedef float ( Base::*MFP )( float const & x ) const;
virtual MFP getMFP( void ) const = 0;
virtual float function( float const & x ) const = 0;
};
class Derived : public Base
{
public:
virtual MFP getMFP( void ) const
{
return &Derived::function;
}
virtual float function( float const & x ) const
{
return x * x;
}
};
class Other
{
public:
float calculate( float const & x, Base * pBase ) const
{
Base::MFP function = pBase->getMFP();
return ( ( *pBase ).*( function ) )( x );
}
};
有没有办法做我在这里想做的事情?
编辑:
对于仍然感兴趣的人,我对我的代码进行了定时测试。事实证明,动态调度仅将我的计算方法减慢了 0.004%,所以几乎没有。使用 MSVC 2010 进行全面优化编译。
您的想法是基于一个不正确的假设,即创建这样的指针会将 VMT 访问带出循环(即执行一次而不是在循环中重复执行)。
C++通过"指针到成员函数"类型的指针(碰巧绑定到虚拟成员函数)的语言调用总是在调用时解析,而不是在初始化时解析。这意味着即使您创建了这样的指针,它也不会优化任何内容。循环中的每个调用仍将执行对 VMT 的全面访问,就像没有任何指针一样。
在C++中,没有办法在初始化时强制这样的指针指向虚拟函数的特定版本。C++语言根本没有这样的特征。
不要这样做。处理器具有深度管道,并且编译器几乎可以肯定已经缓存了函数指针。你可以通过一些努力来做到这一点。但我保证,在任何不到 10 年的编译器上,这不会有什么区别。
我会避免过早优化,直到它成为一个问题;然后,只有这样,在你分析了你的代码之后,你才会进行更改。 首先要考虑可维护性和可扩展性,如果您仍然遇到性能问题,请进行重构。 在此示例中,查找的开销很小。
我宁愿查看可读的代码,也不愿查看性能提高 5% 但需要我一整天才能弄清楚它在做什么的代码。
方法是强制转换,如果您确定 for 循环中的对象是Derived
。
void foo(float);
Base* pObject;
//...
//If you know with certainty that the object is a Derived
Derived& der = *static_cast<Derived*>(object)
for(float x : floatContainer)
{
foo(der.function(x));
}
这意味着您只会调用 Derived
的 vtable,这可能会更快,具体取决于从 Derived
派生的类数量。如果你只能保证这个类是一个Base
,那么你在上面的问题中写的本质上是一个vtable,除了比编译器产生的任何东西慢得多。您可能听说过 vtables 很慢,与原始 C 指针和函数相比,也许这是真的,但我几乎可以完全保证它足够快以满足您的需求。
- 在C#中处理C++指针而不使用unsafe的最佳方法
- C++优先级队列,按对象的唯一指针的特定方法升序排列
- 对于C++中使用智能指针的指针算术限制,有没有一种变通方法
- 有没有一种"cleaner"的方法可以在指向基的指针向量中找到派生类的第一个实例?
- 在c++中为我自己的基于指针的数组分配内存的正确方法
- 将成员函数指针作为参数传递给模板方法
- 通过函数指针定义类范围之外的方法
- 模板方法访问正向声明的类仅在没有此指针的情况下无法编译
- 如何访问由共享指针保存的类方法?
- 初始化指向类实例的智能指针并访问其方法
- 我无法使用C++指针指向类方法返回的 std::vector
- 如何在工厂方法中返回指向基于基础操作系统的派生类的有效指针
- 有没有将变量名称转换为双指针的简短方法?
- 在自定义 std::vector-like 容器中处理指针和非指针模板类型的最佳方法是什么?
- 如何在成为指向基类的指针后保留对子类方法的使用?
- 从纯虚拟类 (A) 派生的指针无法访问来自纯类 (B) 的重载方法
- 类指针方法崩溃程序
- 证明两指针方法有效(对和)
- Qt 删除指针方法
- 我如何将一些类的指针方法转换为指针函数