【发布时间】:2018-12-14 21:19:28
【问题描述】:
我想通过使用 dynamic_cast 来避免对象切片。我正在尝试使用 CRTP 来避免为每个派生类编写赋值运算符。基类是“Shape”,并且有几个派生类(“Circle”就是一个例子)。目的是仅使用其他 Shape 类作为模板,而不为每个类编写赋值运算符,例如 class squre: public ShapeCopyable<square> 但是,编译器在 return *this; 的行抱怨说:
错误 C2440:“return”:无法从“ShapeCopyable”转换为“Circle &”
但它看起来不错,因为继承是这样的:Shape->ShapeCopable->Circle。我应该能够将ShapeCopyable 的对象返回到Circle 的引用,因为它们来自相同的继承层次结构,对吧?错误在哪里?我应该如何解决它?
顺便说一句,Shape* 的向量是各种 Shape 指针的持有者,它持有的指针稍后会分配到它们对应的 Shape(square, circle, etc) 向量中。
代码附在下面。
class Shape {
protected:
string name;
int edges;
virtual void assign(const Shape &rhs) {
name = rhs.name;
edges = rhs.edges;
}
};
template<typename T>
class ShapeCopyable : public Shape
{
public:
T & operator=(const Shape& s)
{
T const& c = dynamic_cast<T const&>(s); // Throws on bad cast.
assign(c);
return *this; //The compiler complains at this line
}
};
class Circle: public ShapeCopyable<Circle> {
private:
int radius;
public:
// preferably, this operator= is not needed.
Circle & operator=(Shape const &rhs) {
ShapeCopyable<Circle>::operator=(rhs);
return *this;
}
Circle(int in = 0) :radius(in) {}
std::string getName() { return name; }
int getEdges() { return edges; }
int getRadius() { return radius; }
void setRadius(int r) { radius = r; }
protected:
void assign(const Circle & rhs) {
Shape::assign(rhs);
radius = rhs.radius;
}
};
main()
{
std::vector<Shape*> shapes;
std::vector<Circle*> circs;
Circle c2(5); //Creates a circle with 5 for the radius.
shapes.push_back(&c2); //Pushing the 5-radius circle into the Shapes* vector
Circle c3; //Creates a circle with default constructor (which does NOT define radius)
c3 = *shapes[0]; //Now, the overloaded assignment operator. Look at Circle::assign(const Shape&) function
circs.push_back(&c3); //We push our newly assigned circle to our Circle vector
std::cout << "c3 radius: " << circs[0]->getRadius(); //This will be 5!
}
【问题讨论】:
标签: templates crtp object-slicing