cout <<s<<": ";
int n=0;
while (!(cin >> n) || n < min || max < n)
{
Clear(cin);
cout <<"\nOut of range: ("<<min<<", "<<max<<")\n"
<< "\nEnter "<<s<<": ";
}
Clear(cin);
return n;
}
//============= Class Man Declaration ==============//
class Man //----- Базовый класс
{
protected: // Данные, передаваемые по наследству
char *name;
int age;
public: // Два конструктора
Man() { name=0; age=0; }
Man (const Man& m)
{
name = strcpy (new char[strlen(m.name)+1], m.name);
age = m.age;
}
~Man() // Деструктор
{
printf("\nDeleting: %s\n", name);
delete [] name;
}
char* Class() { return "Man "; } // Методы, передаваемые по наследству
void In()
{
printf("\n\nName: "); gets(buf);
name = strcpy(new char[strlen(buf) + 1], buf);
age = ::In ("Age", 1,150);
}
void Out()
{
printf ("\n%s %s\t Age: %d", Class(), name, age);
}
};
class Stud : public Man //----- Производный класс
{
protected: // Унаследовал поля имени и возраста
int course; // Завел новое поле
public:
Stud() : Man() // Конструкторы сначала создают объект класса Man
{
course=0;
}
Stud (const Stud& m) : Man(m)
{
course = m.course;
}
char* Class()
{
return strcat (strcpy (buf, Man::Class()), ": Stud");
}
void In() // Переопределенные методы
{
Man::In(); // Вызов родительской версии
course = ::In ("Course", 0, 6);
}
void Out()
{
printf("\n%s", Class());
Man::Out(); // Вызов родительской версии
printf("\tCourse: %d", course);
}
};
class Prof : public Man //----- Еще один производный класс
{
protected: // Унаследовал поля имени и возраста
int publ; // Завел свои уникальные данные
char* dept;
public: // Конструкторы сначала создают объект класса Man
Prof() : Man()
{
publ=0; dept=0;
}
Prof (const Prof& m) : Man(m)
{
publ = m.publ;
dept = strcpy(new char[strlen(m.dept)+1], m.dept);
}
~Prof()
{
printf("\nDeleting: %s\n", dept);
delete [] dept;
}
char* Class()
{
return strcat (strcpy (buf, Man::Class()), ": Prof");
}
void In()
{
Man::In(); // Вызов родительской версии
publ = ::In("Publications", 1, 500);
printf("Dept: ");
gets(buf);
dept = strcpy (new char[strlen(buf)+1], buf);
}
void Out()
{
printf("\n%s", Class());
Man::Out(); // Вызов родительской версии
printf("\tPublications: %d Dept: %s", publ, dept);
}
};
void main()
{
Man man;
man.In(); man.Out(); // Родительские версии методов
printf("\n\n\tClass of Man = %s", man.Class());
printf("\n\tSizeof(Man) = %d", sizeof(Man));
Stud stud;
stud.In(); stud.Out(); // Версии производного класса Stud
printf("\n\n\tClass of Stud = %s", stud.Class());
printf ("\n\tSizeof(Stud) = %d", sizeof(Stud));
Prof prof;
prof.In(); prof.Out(); // Версии производного класса Prof
printf("\n\n\tClass of Prof = %s", prof.Class());
printf ("\n\tSizeof(Prof)=%d", sizeof(Prof));
puts("\n\n");
}
При описании производного класса синтаксис с использованием двоеточия (class Stud : public Man) устанавливает иерархию между классом и подклассом. Таким образом, Man является родительским классом по отношению к классу Stud. Мнемоническое правило «создан класс Студент Мэнович» помогает запомнить, кто есть родитель. В классе Stud, несмотря на отсутствие явных указаний, присутствуют все данные и методы, унаследованные от класса Man, кроме конструктора. Вывод sizeof(Stud) доказывает это утверждение.
Объект класса |
Размер объекта (байт) |
Man |
8 (2 поля по 4 байта) |
Stud |
12 (3 поля по 4 байта) |
Prof |
16 (4 полей по 4 байта) |
Обратите внимание на описатель доступа или прав пользования наследуемыми данными и методами в заголовках производных классов. Наличие описателя public означает, что protected и public члены базового класса при наследовании попадают соответственно в protected и public секции производного класса. Здесь допустима следующая мнемоника: Студент публично заявил, что он сын Человека и наследует все данные и методы своего отца с теми же правами пользования. Если создать класс
class TechnoStud: public Stud;
производный от Студента, то он будет являться сыном Студента и внуком Человека и наследует все имущество и права пользования своих предков. Каждый объект класса TechnoStud, также как и Stud, будет иметь свои собственные копии данных name и age. В методе In класса Stud мы вызываем одноименный метод базового класса Man с целью ввода унаследованных данных. Отметьте, что двойное двоеточие в операторе Man::In(); (:: — scope operator) означает принадлежность метода классу Man, в отличие от одноименного метода класса Stud. Говорят, что метод Stud::In скрывает (hides) наследованный метод, однако операция ::, совместно с описателем Man позволяет получить доступ к родительской версии. Эта же мысль содержится в высказывании: метод In базового класса воспроизведен внутри метода Stud::In. Последний метод не только содержит в себе вызов одноименного метода базового класса, но и дополнен другими операторами. Таким образом, обработка унаследованных данных возложена на метод родительского класса, свое же поле данных (course) обрабатывается своим оператором.
Уважаемый посетитель!
Чтобы распечатать файл, скачайте его (в формате Word).
Ссылка на скачивание - внизу страницы.