![](/img/trans.png)
[英]How can I avoid virtual call overhead when using crtp with common interface class?
[英]How can I call the constructor of the derived class when using CRTP?
我有以下设置:
#include <iostream>
template <typename T>
struct feline {
void roar() noexcept {
static_cast<T*>(this)->do_roar();
}
feline() noexcept {
std::cerr << "Feline ctor" << std::endl;
}
};
struct lion : public feline<lion> {
lion() noexcept : feline() {
std::cerr << "Lion ctor" << std::endl;
}
void do_roar() noexcept {
std::cerr << "Lion roar" << std::endl;
}
};
struct tiger : public feline<tiger> {
tiger() noexcept : feline() {
std::cerr << "Tiger ctor" << std::endl;
}
void do_roar() noexcept {
std::cerr << "Tiger roar" << std::endl;
}
};
int main()
{
feline<lion> lion;
lion.roar();
feline<tiger> tiger;
tiger.roar();
}
当我执行它时,得到以下结果:
Feline ctor
Lion roar
Feline ctor
Tiger roar
这意味着从不调用Lion和Tiger的构造函数。 我该如何实现?
因为您永远不会创造出真正的狮子。
CRTP需要实际类的对象才能正常工作。
请记住,基类永远不会直接实例化子类,因为其全部目的在于强迫该类支持某些功能,而不是经典继承。
您的代码可能会崩溃,但不会崩溃,这是因为do_roar
函数无法访问任何私有变量。 尝试将一些成员添加到lion
并在do_roar
使用它们,您会看到...
如果要让狮子使用lion
类,则feline<lion>
只是feline<T>
的实例,其中T = lion
。
您使用的CRTP略有错误。 暂时忘了基类是在继承类上参数化的事实,那么您要做的事情如下:
struct feline { };
struct lion : feline {};
feline roary; // in your actual code this is parametrized with lion
// but still it is no lion !
当您实际想要制造狮子时:
lion roary; // this is a lion !
您声明了新类,但未使用它们。
下面是使用新类的经过修订的main()
:
int main()
{
lion l;
l.roar();
tiger t;
t.roar();
}
输出:
Feline ctor
Lion ctor
Lion roar
Feline ctor
Tiger ctor
Tiger roar
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.