ООП / ООП / oop-ekz-tasks / Болты, гайки-объясненная, 5 семинар
.doc/*
Имеются болты (Screw), гайки (Nut) и шайбы (Washer) по отдельности. Болт и гайка имеют метрическую или дюймовую резьбу (Thread), шайба - метрический или дюймовый диаметр. В метрической системе диаметр задается целым числом (мм), в дюймовой - дробью из трех цифр (например, 1+1/4 дюйма). Из болта, гайки и произвольного (Z+) числа шайб можно собрать
соединение (Connection). Все болты, гайки, шайбы и соединения являются объектами, хранящимися в динамической памяти. Тип указателя для каждого объекта - указатель на общий базовый класс Thread. Класс Connection является наследником Screw, Nut и Washer. Нарисовать иерархию наследования классов. В каких местах используется виртуальное наследование?
// t- массив указателей, tc-счетчик занятых указателей
// соединение: болт+гайка+2 шайбы, диаметр 6 мм
t[tc++] = new Connection(2,6);
// отдельная гайка, диаметр 6 мм
t[tc++] = new Nut(6);
// отдельная гайка, диаметр 1+1/4 дюйма
t[tc++] = new Nut(1,1,4);
// отдельная шайба, диаметр 1/2 дюйма
t[tc++] = new Washer(0,1,2);
Требуется вычислить количество созданных соединений, гаек, болтов и шайб:
// для приведенного примера:
Соединений: 1
Гаек: 3
Болтов: 1
Шайб: 3
При подсчете потребуется использовать 2 механизма из RTTI:
- dynamic_cast;
- typeid(...).name().
При вызове любого конструктора и деструктора на экран выводить сообщение (например, для класса Nut: "+Nut" для конcтруктора и "-Nut" для деструктора. Объяснить порядок их вызова.
*/
#include <conio.h>
#include <stdio.h>
#include <string.h>
#include <typeinfo.h>
class Thread
{
protected:
bool IsMetric;
int d1, d2, d3;
public:
Thread (int pd1)
{
IsMetric = true;
d1 = pd1;
puts ("+Thread");
}
Thread (int pd1, int pd2, int pd3)
{
IsMetric = false;
d1 = pd1;
d2 = pd2;
d3 = pd3;
puts ("+Thread");
}
virtual ~Thread ()
{
puts ("-Thread");
}
};
class Screw : virtual public Thread
{
public:
Screw (int pd1)
: Thread (pd1)
{
puts ("+Screw");
}
Screw (int pd1, int pd2, int pd3)
: Thread (pd1, pd2, pd3)
{
puts ("+Screw");
}
~Screw ()
{
puts ("-Screw");
}
};
class Nut : virtual public Thread
{
public:
Nut (int pd1)
: Thread (pd1)
{
puts ("+Nut");
}
Nut (int pd1, int pd2, int pd3)
: Thread (pd1, pd2, pd3)
{
puts ("+Nut");
}
~Nut ()
{
puts ("-Nut");
}
};
class Washer : virtual public Thread
{
public:
Washer (int pd1)
: Thread (pd1)
{
puts ("+Washer");
}
Washer (int pd1, int pd2, int pd3)
: Thread (pd1, pd2, pd3)
{
puts ("+Washer");
}
~Washer ()
{
puts ("-Washer");
}
};
class Connection : public Screw, public Nut, public Washer
{
protected:
int Num;
public:
Connection (int n, int pd1)
: Screw (pd1),
Nut (pd1),
Washer (pd1),
Thread (pd1)
{
Num = n;
puts ("+Connection");
}
Connection (int n, int pd1, int pd2, int pd3)
: Screw (pd1, pd2, pd3),
Nut (pd1, pd2, pd3),
Washer (pd1, pd2, pd3),
Thread (pd1, pd2, pd3)
{
Num = n;
puts ("+Connection");
}
~Connection ()
{
puts ("-Connection");
}
int GetNum ()
{
return Num;
}
};
void main ()
{
Thread* t[10];
int tc = 0;
t[tc++] = new Connection (2, 6);
t[tc++] = new Nut (5);
t[tc++] = new Nut (1, 1, 4);
t[tc++] = new Washer (0, 1, 2);
t[tc++] = new Screw (2);
int nc = 0,
ns = 0,
nn = 0,
nw = 0;
/*
Обратите внимание: разные компиляторы возвращают разные имена типов! Чтобы узнать, какие именно имена возвращает ваш компилятор, следует написать что-нибудь типа
puts (typeid(Connection).name());
Например, компиляторы Microsoft вернут "class Connection", а компиляторы Borland вернут "Connection". В контрольной следовало указать, под какой компилятор и какой версии вы писали код :)
*/
for (int i = 0; i < tc; ++i)
{
if (strcmp(typeid(*t[i]).name(), "Screw") == 0)
++ns;
if (strcmp(typeid(*t[i]).name(), "Nut") == 0)
++nn;
if (strcmp(typeid(*t[i]).name(), "Washer") == 0)
++nw;
if (strcmp(typeid(*t[i]).name(), "Connection") == 0)
{
++nc;
++ns;
++nn;
nw += (dynamic_cast <Connection*> (t[i]))->GetNum ();
}
}
printf ("S = %d, N = %d, W = %d, C = %d\n", ns, nn, nw, nc);
for (int i = 0; i < tc; ++i)
delete t[i];
getch ();
}