如果使用CRTP,派生类方法是否覆盖方法的基类版本? 几天前,我发现了一个有趣的C++构造,名为奇怪的重复模板模式(通常在缩写CRTP下已知)。从那时起,我一直试图完全理解这个技巧是如何工作的
假设我有以下代码片段如果使用CRTP,派生类方法是否覆盖方法的基类版本? 几天前,我发现了一个有趣的C++构造,名为奇怪的重复模板模式(通常在缩写CRTP下已知)。从那时起,我一直试图完全理解这个技巧是如何工作的,c++,inheritance,crtp,static-polymorphism,C++,Inheritance,Crtp,Static Polymorphism,假设我有以下代码片段 #include <iostream> template<class T> struct GraphicalObject { void draw() { static_cast<T*>(this)->draw(); } }; struct Circle : GraphicalObject<Circle> { void draw() { std::
#include <iostream>
template<class T>
struct GraphicalObject
{
void draw()
{
static_cast<T*>(this)->draw();
}
};
struct Circle : GraphicalObject<Circle>
{
void draw()
{
std::cout << "Drawing circle!" << std::endl;
}
};
struct Square : GraphicalObject<Square>
{
void draw()
{
std::cout << "Drawing square!" << std::endl;
}
};
int main(int argc, char** argv) {
Square s;
Circle c;
s.draw();
c.draw();
return 0;
}
因此,创建了具有特殊版本的draw
方法的struct。结构GraphicalObject
构成圆
结构的基础结构
在第二步中,创建
Circle
结构的实例c
,即调用Circle
的隐式构造函数。由于圆
是从GraphicalObject
继承的,因此首先调用该结构的隐式构造函数。在我看来,这将导致在c
对象内部创建GraphicalObject
的实例。是这样吗?然后我认为draw
方法在Circle
结构中声明,它覆盖了GraphicalObject
结构中声明的draw
方法。但这对我来说没有意义。我更希望从GraphicalObject
提交的draw
方法的“专用”版本不会被覆盖。请您告诉我,我对CRTP工作原理的理解有什么错误?您没有在main
中进行任何多态性操作,这将演示CRTP的功能。试试这个,看看会发生什么:
模板
void drawObject(GraphicalObject和obj){
obj.draw();
}
int main(){
正方形s;
圈c;
s、 draw();
c、 draw();
drawObject;//这里发生了什么?
图形对象&c_ref=c;
drawObject(c_ref);//这里发生了什么?
}
Circle::draw
不会覆盖GraphicalObject::draw
(作为非虚拟对象),而是隐藏它。实际上,我们的想法是使用不同的名称。@Jarod42感谢您的回复。这是否意味着我对CRTP工作原理的理解基本正确,但Circle::draw
隐藏了GraphicalObject::draw
,而不是覆盖它?感谢您的回复。我是否正确理解,如果我调用drawObject
,将进行切片,并将s
切片到GraphicalObject
。因此,首先调用了draw
方法的多态版本?我想您已经找到了。drawObject
中的“切片”(obj
)调用基类draw
方法,然后该方法依次调用子类draw
。这允许您创建伪虚拟函数,而无需将其定义为虚拟
(即静态多态性)。
struct GraphicalObject<Circle>
{
void draw()
{
static_cast<Circle*>(this)->draw();
}
};