Итак, у меня есть базовый класс (Shape) и три производных класса, Circle, Rectangle и Square (Square является производным от Rectangle). Я пытаюсь реализовать оператор<< который просто вызывает правильную функцию отображения для того, что вызвало его. Однако я не думаю, что у меня правильный синтаксис. Вот фрагмент — где я ошибся?
class Shape
{
public:
Shape(double w = 0, double h = 0, double r = 0)
{
width = w;
height = h;
radius = r;
}
virtual double area() = 0;
virtual void display() = 0;
protected:
double width;
double height;
double radius;
};
ostream & operator<<(ostream & out, const Shape & s)
{
s.display(out);
return out;
}
class Rectangle : public Shape
{
public:
Rectangle(double w, double h) : Shape(w, h)
{
}
virtual double area() { return width * height; }
virtual void display()
{
cout << "Width of rectangle: " << width << endl;
cout << "Height of rectangle: " << height << endl;
cout << "Area of rectangle: " << this->area() << endl;
}
};
Ты звонишь display
как это:
s.display( out );
Но display
определяется как:
vritual void display() = 0;
Функция была объявлена и определена без параметров. Следует принять ссылку на std::ostream
в качестве параметра:
virtual void display(std::ostream &) = 0;
Это также должно быть const
метод, как вы передаете в const
объект через operator <<
перегрузка:
virtual void display(std::ostream &) const = 0;
Не забывайте, что в определении display
Вы должны писать в ostream
объект, а не конкретно std::cout
,
Вот программа компиляции на Ideone.
У вас есть ряд проблем здесь. Во-первых, давайте разберемся с проблемой печати:
ostream & operator<<(ostream & out, const Shape & s)
Здесь вы проходите const Shape
, Это означает, что вы можете только позвонить const
методы на s
вы передаете. Однако вы не пометили ни один из методов в базовом (или производном) классе как const
, ни area
ни display
следует изменить состояние объекта. Во-вторых, вы пытаетесь позвонить s.display(out)
прохождение ostream&
в display
, Подпись функции, которую вы имеете, не отражает это. Итак, сложив все вместе, мы получим:
virtual double area() const = 0;
virtual void display(ostream& out) const = 0;
У вас также есть некоторые другие проблемы — базовый класс, который не объявляет виртуальный деструктор. Если вы планируете использовать класс полиморфно, это должен есть виртуальный деструктор:
virtual ~Shape() { }
Вам также необходимо изменить ваши методы в производном классе:
double area() const { return width * height; }
void display(ostream& out) const
{
out << "Width of rectangle: " << width << endl;
out << "Height of rectangle: " << height << endl;
out << "Area of rectangle: " << area() << endl;
}
Обратите внимание, что display
в Rectangle
всегда печатал cout
заранее.
Вы почти правильно поняли, вот рабочее решение:
#include <iostream>
using std::cout;
using std::endl;
using std::ostream;
class Shape
{
public:
Shape(double w = 0, double h = 0, double r = 0)
{
width = w;
height = h;
radius = r;
}
virtual ~Shape() {} // Recommended!
virtual double area() const = 0;
virtual void display(ostream & out) const = 0;
protected:
double width;
double height;
double radius;
};
ostream & operator<<(ostream & out, const Shape & s)
{
// Since `s` is `const`, then `display` method should be `const` too.
s.display(out);
return out;
}
class Rectangle : public Shape
{
public:
Rectangle(double w, double h) : Shape(w, h)
{
}
virtual double area() const { return width * height; }
virtual void display(ostream & out) const
{
// Since `display` method is `const`, then `area` method should be
// `const` too.
out << "Width of rectangle: " << width << endl;
out << "Height of rectangle: " << height << endl;
out << "Area of rectangle: " << this->area() << endl;
}
};void main() {
Rectangle r(1, 2);
cout << r << endl;
}
Пожалуйста, обратите внимание на const
квалификаторы, которые обеспечивают const
-correctness методов класса. Я добавил несколько полезных комментариев, чтобы вы могли плавно следовать логике. Возьмите это за правило, если метод не изменяет членов класса, то вы должен объявить это const
,