В следующем коде в функции main форма объявлена как указатель на объект класса Shape, но адрес объекта класса Rectangle, а именно rec, сохранен в следующей строке. Может кто-нибудь сказать мне, где я ошибаюсь в моем понимании.
class Shape {
protected:
int width, height;
public:
Shape( int a=0, int b=0)
{
width = a;
height = b;
}
int area()
{
cout << "Parent class area :" <<endl;
return 0;
}
};
class Rectangle: public Shape{
public:
Rectangle( int a=0, int b=0)
{
Shape(a, b);
}
int area ()
{
return (width * height);
}
};
class Triangle: public Shape{
public:
Triangle( int a=0, int b=0)
{
Shape(a, b);
}
int area ()
{
return (width * height / 2);
}
};int main( )
{
Shape *shape;//pointer to Shape class
Rectangle rec(10,7);
Triangle tri(10,5);shape = &rec;//address of Rectangle class object saved
shape->area();
shape = &tri;
shape->area();
return 0;
}
Shape
должен объявить area
как virtual
получить полиморфное поведение.
virtual int area()
{
...
}
В вашем коде есть несколько ошибок, и в результате код не имеет смысла.
Рассмотрим для примера конструктор
Triangle( int a=0, int b=0)
{
Shape(a, b);
}
Сначала будет вызван конструктор по умолчанию Shape, потому что вы не указали вызов конструктора Shape в списке инициализации ctor. Таким образом, ширина и высота будут установлены в ноль конструктором по умолчанию.
Внутри тела конструктора Triangle вы просто создаете временный объект типа Shape, который никогда не будет использоваться.
Это может выглядеть как унылый путь
Triangle( int a=0, int b=0) : Shape( a, b ) {}
или даже как
explicit Triangle( int a=0, int b=0) : Shape( a, b ) {}
если вы знаете, что означает явное.
Помимо этого иерархия классов должна основываться на виртуальных функциях, которые вы могли бы получить эффект от полиморфизма. Поэтому класс Shape должен быть определен следующим образом
class Shape {
protected:
int width, height;
public:
Shape( int a=0, int b=0) : width( a ), height( b ) {}
virtual ~Shape() {}
virtual int area() const = 0;
};
int Shape::area() const
{
cout << "Parent class area :" <<endl;
return 0;
}
И uodate производные классы в соответствии с этими изменениями.
Rectangle
происходит от Shape
смотрите строчку
class Rectangle: public Shape
Это называется наследованием или отношением «is-a»: Rectangle
это Shape
, Следовательно, Shape*
может указывать на прямоугольник. Больше информации, например, можно найти в Указатель базового класса против унаследованного указателя класса? или большинство учебников по C ++, охватывающих наследование.
Как отмечает ответ Родди, вы должны заявить area
в Shape
как virtual
иначе звоню shape->area()
всегда буду звонить Shape
«s area
метод вместо переопределенного метода, предоставляемого Rectangle
, поскольку area
за Shape
на самом деле не имеет смысла, вы могли бы даже рассмотреть вопрос об объявлении его как чисто виртуальный:
virtual int area() = 0;