Я бы хотел избежать нарезки объектов с помощью 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 (квадрат, круг и т. Д.) В дальнейшем.
Код прилагается ниже.
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!
}