这是静态多态性的 CRTP 用法,但没有实现派生函数。在 gcc 和 Visual Studio 中编译。为什么?
#include <iostream>
template <class Derived>
class Base
{
public:
void method1()
{
static_cast<Derived*>(this)->method1();
}
void method2()
{
static_cast<Derived*>(this)->method2();
}
};
class Derived1: public Base<Derived1>
{
public:
void method1()
{
std::cout << "Method 1 of Derived1 executed.\n";
}
};
int main(int argc, char *argv[])
{
Derived1 d1;
d1.method1();
d1.method2();
return 0;
}
后续问题:如何使这种类型安全?也就是说,如果有人忘记实现 method2,我希望编译器能够捕获它。我不希望它在运行时爆炸。
#include <iostream>
template <class Derived>
class Base
{
public:
void method1()
{
static_cast<Derived*>(this)->method1();
}
void method2()
{
static_cast<Derived*>(this)->method2();
}
};
class Derived1: public Base<Derived1>
{
public:
void method1()
{
std::cout << "Method 1 of Derived1 executed.\n";
}
};
int main(int argc, char *argv[])
{
Derived1 d1;
d1.method1();
d1.method2();
return 0;
}
Follow up question: How to I make this type safe? That is, If someone forgets to implement method2, I would like the compiler to catch it. I don't want this to blow up at runtime.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
我认为这是有效的原因是,如果您实例化此代码:
其中
Derived
没有method2()
的实现本质上将是一个美化的自递归调用。这里的原因是,在Derived1
中,确实有一个名为method2
的成员函数,即从基类继承的函数。我尝试运行这段代码,果然对
method2
的调用导致了自递归的堆栈溢出。通常,CRTP 通过不让基类函数调用同名的派生类函数来避免这种情况。这样,如果派生类缺少特定函数,则调用会触发编译器错误。在您的情况下,这种情况不会发生,因为函数本身可以从基类间接引用。
I think the reason that this is valid is that if you instantiate this code:
where
Derived
does not have an implementation ofmethod2()
will essentially be a glorified self-recursive call. The reason here is that inDerived1
, there is indeed a member function calledmethod2
, namely the one inherited from the base class.I tried running this code, and sure enough the call to
method2
caused a stack overflow from self-recursion.Normally, the CRTP avoids this by not having the base class function call a derived class function of the same name. That way, if the derived class is missing a particular function, the call triggers a compiler error. In your case, this doesn't happen because the function itself could be referenced indirectly from the base class.
尽管
Derived1
没有定义method2()
,但它还是通过继承Base
来获取它。这就是它编译和运行的原因。d1.method2()
实际上调用了Base::method2()
,后者又调用了自身。这是一个递归调用。Even though
Derived1
doesn't definemethod2()
, it gets it by inheritingBase
anyway. That is why it compiles and runs.d1.method2()
actually callsBase::method2()
, which again calls itself. It's a recursive call.