避免虚成员函数开销
CRTP to avoid virtual member function overhead
在CRTP中,为了避免动态多态性,提出了以下解决方案,以避免虚成员函数的开销,并强加一个特定的接口:
template <class Derived>
struct base {
void foo() {
static_cast<Derived *>(this)->foo();
};
};
struct my_type : base<my_type> {
void foo() {}; // required to compile. < Don't see why
};
struct your_type : base<your_type> {
void foo() {}; // required to compile. < Don't see why
};
然而,派生类似乎不需要定义来编译,因为它继承了一个定义(代码编译良好,没有定义my_type::foo)。实际上,如果提供了函数,则在使用派生类时不会调用基函数。
所以问题是,以下代码替换是否可以接受(并且是标准的?):template <class Derived>
struct base {
void foo() {
// Generate a meaningful error if called
(void)sizeof( Derived::foo_IS_MISSING );
};
};
struct my_type : base<my_type> {
void foo() {}; // required to compile.
};
struct your_type : base<your_type> {
void foo() {}; // required to compile.
};
int main() {
my_type my_obj;
my_obj.foo(); // will fail if foo missing in derived class
}
这个模式的要点是,据我所知,您可以简单地作为template <typename T> base<T> &
传递参数,并且您的接口由base<T>
中的(非虚)函数定义。如果您没有想要定义的接口(正如您在问题的第二部分所建议的那样),那么首先就不需要这些。
在您的替换代码中,您不能"多态"调用foo
对base<T>
。
然而,派生类似乎不需要定义来编译,因为它继承了一个 (代码编译良好,而不定义 my_type::foo)。
c++是懒惰的:如果你不实际使用base
template <class Derived>
struct base {
void foo() {
static_cast<Derived *>(this)->foo();
};
};
struct my_type : base<my_type> {};
void func() {
my_type m;
static_cast<base<my_type>& >(m).foo();
}
可以很好地编译。当编译器呈现Static_cast (this)->foo(),它将尝试找到一个可以在my_type中访问的foo()。有一个:它被称为base
不,想象一下以下情况:
template <typename T>
void bar(base<T> obj) {
obj.foo();
}
base<my_type> my_obj;
bar(my_obj);
Base的foo将被调用,而不是my_type的…
这样做,你会得到错误消息:
template <class Derived>
struct base {
void foo() {
sizeof(Derived::foo);
static_cast<Derived *>(this)->foo();
};
};
但是我必须承认我不确定这将如何在GCC以外的编译器中工作,只使用GCC进行测试。
相关文章:
- 类型擦除的std::function与虚拟函数调用的开销
- 在编译时评估函数开销的通用方法
- 在循环中调用同一虚函数的开销
- 使用静态成员函数而不是普通函数是否有任何开销?
- 使用递归模板函数是否会引入函数调用开销,或者编译器是否大部分时间都内联它(下面的示例)?
- 如果类没有任何成员变量,则通过临时对象调用类的成员函数的开销是多少?
- 减少非静态成员函数开销
- 如何最大限度地减少使用标量 SIMD 内部函数的 SIMD 注册表的双重负载开销
- 函数调用在C++中有明显的开销吗
- 快速交叉乘积.函数调用开销
- 为什么异常总是在具有可破坏堆栈对象的非叶函数中产生开销
- 每次调用负0.6ns的虚拟函数开销
- 最小化函数选择和函数调用开销
- 调用链函数是否会产生开销
- C++:如果所有数据可能都已有效,则在构造函数中进行验证是否有开销
- boost::lock_guard分配、构造函数和析构函数开销
- 确定性时的虚函数开销 (C++)
- 避免虚成员函数开销
- C++非静态成员函数开销
- 结构变成类-明显的函数开销?c++