Standardowy przykład. Dajmy na to, że tworzysz prosty program graficzny (obiektowo), który ma rysować figury geometryczne. Masz obiekt klasy Painter:
class Painter
{
public:
void Draw(int x, int y, const Shape & s)
{
s.DoDraw(x, y);
}
}
Painter ma za zadanie "powiedzieć" innym obiektom, że mają się rysować i gdzie. Klasa shape jest klasą abstrakcyjną (nie możesz narysować "kształtu". Bo czym jest kształt?)
class Shape
{
protected:
virtual void DoDraw(int x, int y) = 0;
friend class Painter;
}
Tutaj trochę wybiegłem. Jeśli nie wiesz, co to friend, to nie zwracaj uwagi. Równie dobrze może tego nie być, a DoDraw może być metodą publiczną, a nie chronioną. W każdym razie, jak już mówiłem "kształtu" jako takiego nie możesz narysować (no bo jak?). Ale kształt jako taki stanowi świetną bazę do tych Twoich figur. Weźmy np. kółko:
class Circle: protected Shape
{
protected:
virtual void DoDraw(int x, int i) override
{
//tutaj w magiczny sposób rysujemy kółko
}
}
Dalej możemy mieć kwadrat:
class Square: protected Shape
{
protected:
virtual void DoDraw(int x, int i) override
{
//tutaj w magiczny sposób rysujemy kwadrat
}
}
(mogłem coś pomylić ze specyfikatorami dostępu, ale piszę z głowy)
Dzięki czemu w klasie Painter nie musisz mieć osobnych funkcji do rysowania każdej figury. Każda figura wie sama, jak ma się narysować. Magia :)
A czemu nie chcesz osobnych metod do rysowania każdej figury? Bo to złe. Wyobraź sobie, że masz teraz rysować trójkąt. No to co. Musisz najpierw rozkminić obiekt Painter, potem go zmienić w taki sposób, żeby umiał narysować trójkąt. Ale po co tak? Jest to zła zmiana. Lepiej utworzyć nową klasę o nazwie Triangle dziedziczącą po Shape.
I dzięki temu możesz zrobić coś takiego:
Painter p;
Circle c;
Square sq;
p.Draw(0, 0, c); //i kółko narysowane
p.Draw(10, 10, sq); //i kwadrat narysowany
//a teraz tworzysz gdzieś nową klasę do rysowania trójkątów i:
Triangle t;
p.Draw(100, 100, t); //i trójkąt narysowany.
A możesz zrobić to wszystko dzięki temu, że twoje kółko jest kształtem. Kwadrat jest kształtem. Trójkąt też jest kształtem (wszystko dziedziczy po Shape, a więc jest w pewnym sensie obiektem typu Shape). Rozumiesz?