我想避免使用dynamic_cast进行对象切片。我正在尝试使用CRTP来避免为每个派生类编写赋值运算符。基本类是“ Shape”,并且有几个派生类(“ Circle”是一个示例)。目的是仅使用其他Shape
类作为模板,而无需为它们每个编写类的赋值运算符,例如class squre: public ShapeCopyable<square>
。但是,编译器在return *this;
行中抱怨:>
错误C2440:“返回”:无法从“ ShapeCopyable”转换为“ Circle&”
但是对我来说这没问题,因为继承是这样的:Shape-> ShapeCopable-> Circle。我应该能够将ShapeCopyable
的对象返回到Circle
的引用,因为它们来自相同的继承层次结构,对吗?错误在哪里?我应该如何解决?
顺便说一句,Shape *的向量是所有Shape指针的持有者,它所保持的指针将在以后分配给它们对应的Shape(正方形,圆形等)向量。
代码附在下面。
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!
}
答案 0 :(得分:0)
更改行:
return *this; //The compiler complains at this line
对此:
return dynamic_cast<T&>(*this);
编译器抱怨的原因是,当编译器期望引用诸如Circle或Square之类的具体形状时,您试图返回ShapeCopyable。
从对基类的引用到对派生类的引用都没有隐式转换,这需要强制转换。
答案 1 :(得分:0)
好吧,我正在回答我自己的问题...经过以下修复后,代码按预期运行。
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.
static_cast<T*>(this)->assign(c); //this line got fixed
return dynamic_cast<T&>(*this); //this line got fixed
}
};
class Circle: public ShapeCopyable<Circle> {
private:
int radius;
public:
using Shapecopyable<Circle>::operator=; //this line got fixed
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; }
//The rest code is the same as before
...
...
}