Rob*_*son 2 c++ templates crtp c++11
说我有以下代码:
template <class Derived>
class Base {
public:
virtual void foo_impl() = 0;
void foo() {
static_cast<Derived*>(this)->foo_impl(); //A
(*static_cast<Derived*>(this)).foo_impl(); //B
}
};
class Derived : public Base<Derived> {
private:
void foo_impl() {
bar();
}
};
Run Code Online (Sandbox Code Playgroud)
几个问题:
A行会生成虚函数调用吗?虽然我在互联网上找到的大部分内容都建议以这种方式做事,但对于我来说,我并没有看到编译器如何进行静态调度,因为指向Derived的指针实际上仍然可以指向Derived2类型的对象,其中Derived2:公共派生.
B行是否解决了我之前提到的问题(如果适用)?考虑到现在调用不再是指针而是因此使用*,它似乎会这样.会避免虚函数调用.但是如果编译器将解除引用的强制转换视为引用类型,它仍然可以生成虚函数调用......在这种情况下,解决方法是什么?
将C++ 11 final关键字添加到foo_impl()会改变编译器在(或任何其他相关)情况下的行为方式吗?
A行会生成虚函数调用吗?
是的.foo_impl()是虚拟的并Derived覆盖它.即使foo_impl()in Derived未明确标记为virtual,它也在基类中,这足以使其成为虚函数.
B行是否解决了我之前提到的问题(如果适用)?
不.无论调用是在指针上还是在引用上都无关紧要:编译器仍然不知道您是foo_impl()在一个派生自 Derived或直接实例的类的实例上调用该函数Derived.因此,通过vtable执行调用.
看看我的意思:
#include <iostream>
using namespace std;
template <class Derived>
class Base {
public:
virtual void foo_impl() = 0;
void foo() {
static_cast<Derived*>(this)->foo_impl();
(*static_cast<Derived*>(this)).foo_impl();
}
};
class Derived : public Base<Derived> {
public:
void foo_impl() {
cout << "Derived::foo_impl()" << endl;
}
};
class MoreDerived : public Derived {
public:
void foo_impl() {
cout << "MoreDerived::foo_impl()" << endl;
}
};
int main()
{
MoreDerived d;
d.foo(); // Will output "MoreDerived::foo_impl()" twice
}
Run Code Online (Sandbox Code Playgroud)
最后:
是否添加C++ 11 final关键字来
foo_impl()改变编译器在(或任何其他相关)情况下的行为方式?
从理论上讲,是的.该final关键字将无法在子类中覆盖该函数Derived.因此,当foo_impl()通过指针执行函数调用时Derived,编译器可以静态地解析调用.但是,据我所知,C++标准不要求编译器这样做.
结论:
无论如何,我相信你真正想要做的就是不要foo_impl()在基类中声明这个函数.使用CRTP时通常就是这种情况.此外,您必须声明类Base<Derived>一friend的Derived,如果你想要访问Derived的private功能foo_impl().否则,你可以foo_impl()公开.
| 归档时间: |
|
| 查看次数: |
1863 次 |
| 最近记录: |