Объектно-ориентированное программирование, страница 16

    "\n\t\tt - Toggle Ascending-Descending"

    "\n\t\tq - Don't Sort\n\n";

char c;

cin >> c; Clear(cin);

return tolower(c);

}

char ManMenu()

{

cout << "\n\t\ts - Stud"

    "\n\t\tp - Prof"

    "\n\t\tq - Stop\n\n";

char c;

cin >> c; Clear(cin);

return tolower(c);

}

//============== Base Abstract Class Man =====================//

class Man

{

friend class Node;

friend class List;

protected:

string name;

int age;

public:

static eSortBy sortBy, lastSortBy; // Режим сортировки списка людей

static bool sortAsc;    // Порядок сортировки списка

Man();

virtual ~Man();

virtual string Class()=0;    //==== Чисто виртуальный метод

virtual string ToString();

virtual void In();

virtual void Read (string& line);

void Out (int id);

void Write (ofstream& os);

string Name();

bool operator< (Man& m);

};

//===================== Derived Class Stud =====================//

class Stud : public Man

{

friend class Node; 

protected:

int course;

public:

Stud();

virtual ~Stud();

virtual string Class();

virtual string ToString();

virtual void In();

virtual void Read (string& line); 

};

//===================== Derived Class Prof =====================//

class Prof : public Man

{

friend class Node;

protected:

int publ;

string dept;

public:

Prof();

virtual ~Prof();

virtual string Class();

virtual string ToString();

virtual void In();

virtual void Read (string& line);

};

Далее следует разработать коды, реализующие методы классов Man, Stud и Prof. Ориентируйтесь на подсказки.

//=============== Class Man implementation =================//

//=============== Static variables

eSortBy Man::sortBy = ByName,     // Режим и порядок сортировки списка

  Man::lastSortBy = ByName;

bool Man::sortAsc = true;

Man::Man () { }    // Инициализируйте данные класса

Man::~Man()

{

cout << " Man: " << name << " is dying";

name.erase();

}

void Man::In()

{

cout << "\nName:  ";

Clear (cin);

//======= Введите строку символов в буфер buf

Clear (cin);

//==== Инициализируйте имя name =

//==== Инициализируйте возраст (с помощью глобальной функции::In)

}

string Man::ToString()

{

return Name() + "; Age: " + itoa(age, buf, 10);

}

string Man::Name()

{

return name; //==== Добавьт подушку из пробелов + string (

}

bool Man::operator< (Man& m)

{

switch (Man::sortBy)

{

default:

case None:  return false;

//==== Добавьте другие ветви сравнения объектов (по имени, по возрасту и по статусу)

}

}

void Man::Out(int id)

{

cout << endl << id << ".\t" << ToString();

}

void Man::Read (string& line)

{

name = line.substr (1, line.find_first_of(';') - 1);

//==== Продолжите синтаксический анализ строки line

}

void Man::Write(ofstream& os)

{

os << endl << ToString();

}

//============== Class Stud implementation =============//

Stud::Stud() : Man()

{

course = 0;

}

Stud::~Stud()

{

cout << "\nStudent: ";

}

//==== Реализуйте чисто виртуальный метод Class()

void Stud::In()

{

//==== Вызовите родительскую версию

//==== Инициализируйте курс (с помощью глобальной функции::In) course =

}

string Stud::ToString()

{

return //==== Используйте родительскую версию и дополните ее

}

void Stud::Read (string& line)

{

//==== Используйте родительскую версию и дополните ее

}

//============= Class Prof implementation =============//

Prof::Prof() : Man()

{

publ = 0;

}

Prof::~Prof()

{

cout << "\nProfessor: ";

}

//==== Реализуйте чисто виртуальный метод Class()

//==== Продолжайте далее (аналогично классу Stud)

void Prof::In()

{

}

string Prof::ToString()

{

}

void Prof::Read (string& line)

{

}

Класс Node (узел списка) содержит указатель man на один из объектов из иерархии Man и указатель next на следующий узел списка, что позволяет организовать связанный список. Нулевое значение этого указателя next в каком-либо объекте означает, что он стоит последним в списке. Указатели man узлов списка ссылаются на объекты классов, производных от класса Man, но, благодаря совместимости классов на уровне указателей, работа идет только с указателями на базовый класс.

Каждый объект классов Stud и Prof содержит унаследованные от класса Man поля: name и age. Главное, что иллюстрируется в этом примере, является полиморфизм позднего связывания, приводимый в действие с помощью виртуальных функций. Функции ввода являются виртуальными и они переопределены (overriden) в производных классах. Несмотря на общность сути методов ввода для объектов всех классов в иерархии, детали ввода и вывода в разных классах разные, так как типы полей данных в них отличаются. Синтаксис, использующий присвоение нуля при объявлении функции virtual string Class()=0; служит для обозначения чисто виртуальной функции, которая не имеет и не может иметь тела в базовом классе. Она должна быть переопределена и наполнена кодами только в производных классах.

Другие функции ввода не являются чисто виртуальными, а лишь просто виртуальными, поэтому они имеют коды реализации и в базовом классе. Класс, имеющий чисто виртуальные функции, автоматически переходит в разряд абстрактных классов. Объекты таких классов не могут быть созданы. Следовательно, мы не сможем создать объект абстрактного типа Маn а только конкретного: Stud или Prof. Здесь нет особой необходимости поступать именно таким образом. Цель приведенных способов описания есть иллюстрация возможностей. Виртуальные функции позволят нам на этапе выполнения программы выбирать конкретные тела методов ввода-вывода в зависимости от принадлежности объекта, на который ссылается указатель типа (Man*), одному из конкретных классов иерархии. В каждом из подклассов воспроизведены методы базового класса, которые служат для ввода общих полей данных.

Динамический список