Файл: Лабораторная работа работа с родительскими и дочерними классами.docx
ВУЗ: Не указан
Категория: Не указан
Дисциплина: Не указана
Добавлен: 02.12.2023
Просмотров: 36
Скачиваний: 1
ВНИМАНИЕ! Если данный файл нарушает Ваши авторские права, то обязательно сообщите нам.
8 ЛАБОРАТОРНАЯ РАБОТА № 8.
РАБОТА С РОДИТЕЛЬСКИМИ И ДОЧЕРНИМИ КЛАССАМИ
-
Общие рекомендации по работе с родительскими и дочерними классами
Цель лабораторной работы - освоение технологий программирования задач, работающих с родительскими и дочерними классами.
Класс, который наследуется другим классом, называется базовым или родительским. Класс, выполняющий наследование, называется производным или дочерним. При этом как у одного базового класса может быть несколько родительских (множественное наследование), так и у одного родительского класса может быть несколько базовых классов.
Спецификаторы доступа при наследовании
В С++ экземпляры класса разделяют в соответствии с правами доступа на следующие три категории: открытые (public), закрытые (private) и защищенные (protected).
Статус доступа к экземплярам производного класса зависит от того, с каким спецификатором доступа объявляется наследование базового класса. Общая форма наследования классов имеет следующий вид:
class имя_производного_класса: доступ имя_базового_класса
{
// код
};
Здесь доступ определяет, каким способом наследуется базовый класс. Спецификатор доступа может принимать одно из трех значений: private, protected, public. Если он не указан, то: подразумевается public для производных классов, объявленных через struct, и private – для объявленных через class.
Если спецификатор принимает значение public, то все открытые и защищенные экземпляры базового класса становятся соответственно открытыми и защищенными экземплярами производного класса.
Если указан protected, то все открытые и защищенные экземпляры базового класса становятся защищенными экземпляры производного класса.
Если указан private, то все открытые и защищенные экземпляры базового класса становятся закрытыми экземплярами производного класса.
Деструкторы производных классов
В деструкторе производного класса компилятор автоматически генерирует вызовы деструкторов его базовых классов.
Для удаления объекта производного класса следует сделать деструктор в базовых классах виртуальным с целью корректного вызова деструкторов при использовании оператора delete.
Передача параметров в базовый класс
Когда базовый класс имеет конструктор с аргументами, производные классы должны передавать базовому классу необходимые аргументы. Для этого используется расширенная форма конструкторов:
порожденный_конструктор(список_аргументов):
базовый1(список_аргументов1),
…,
базовыйN(список_аргументовN)
{
// код
}
Здесь под базовый1, …, базовыйN обозначены имена базовых классов. С помощью двоеточия конструктор производного класса отделяется от списка конструкторов базового класса. Списки аргументов, передаваемых в конструкторы базовых классов, могут состоять из констант, глобальных переменных или параметров конструктора производного класса.
Если конструкторы производных классов не вызываются в явном виде (как в примере выше), вместо них из базовых классов автоматически вызываются конструкторы без параметров. Кроме того, конструкторы без параметров автоматически вызываются при инициализации вместо указанных конструкторов с параметрами в случае, если имеет место виртуальное наследование (см. ниже).
Указатели и ссылки на производные классы
В общем случае указатель одного типа не может указывать на объект другого типа, однако в С++ указатель на базовый класс может указывать на объект производного класса. Ссылки на базовый класс могут быть использованы для ссылок на объект производного типа.
Виртуальные функции
Виртуальная функция – это функция, объявленная с ключевым словом virtual в базовом классе и переопределенная в производных классах.
Это означает, что при использовании объекта производного класса с помощью указателя или ссылки на него как на объект базового класса, виртуальная функция вызывается из того класса, посредством которого этот объект был создан. То есть, в одном и том же участке кода для разных объектов могут вызываться разные версии одной и той же виртуальной функции. Класс, содержащий хотя бы одну виртуальную функцию, называется полиморфным классом.
Для виртуальных функций существуют следующие правила:
– виртуальную функцию нельзя объявлять как static;
– спецификатор virtual необязателен (но желателен) при переопределении функции в производном классе.
-
Пример программы с виртуальными функциями
#include
#include
using namespace std;
class creature
{
private:
string title;
double mass;
public:
creature() :mass(0.0) {} // конструктор без параметров
// конструктор копирования
creature(const creature& obj):title(obj.title), mass(obj.mass){}
// конструктор с параметрами
creature(const string& _title, double _mass) : title(_title), mass(_mass) {}
// деструктор (объявлен как виртуальный)
virtual
creature() { cout << "creature deleted" << endl << endl; }
protected:
// защищенная виртуальная функция для вывода информации об объекте
// не должна использоваться вне данного класса и его производных
virtual void _print() const
{
cout << "title: " << title << endl;
cout << ", mass: " << mass << endl;
}
public:
// открытая функция для вывода информации об объекте
void print() const
{
// выводит название класса, к которому принадлежит
// объект, для которого она вызвана,
cout << typeid(*this).name() << ": (";
// и вызывает виртуальную функцию
// т.к. функция _print виртуальная, вызываться она
// будет не только из текущего класса, но и из производных,
// в зависимости от того, для какого объекта
// осуществляется вызов
_print();
cout << ")" << endl;
}
};
// класс animal наследуется от класса creature
class animal : public creature
{
private:
double speed; // m/s
public:
// конструкторы класса animal осуществляют вызовы
// конструкторов
// базового класса (creature)
animal(): creature(), speed(0.0) {}
animal(const animal& obj): creature(obj), speed(obj.speed) {}
animal(const string& _title, double _mass, double _speed): creature(_title, _mass), speed(_speed){}
animal() { cout << "animal deleted" << endl; }
protected:
// виртуальная функция _print переопределяется в
// производном классе
void _print() const
{
creature::_print();
cout << ", speed: " << speed;
}
};
// класс bird наследуется от класса animal
class bird : public animal
{
private:
double topfly; // km
public:
bird(): animal(), topfly(0.0) {}
bird(const bird& obj): animal(obj), topfly(obj.topfly){}
bird(const string& _title, double _mass, double _speed, double _topfly):
animal (_title, _mass, _speed), topfly(_topfly) {}
bird() { cout << "bird deleted" << endl; }
protected:
// виртуальная функция _print переопределяется
// теперь уже в классе bird
void _print() const
{
animal::_print();
cout << ", topfly: " << topfly;
}
};
// класс fish наследуется от класса animal
class fish : public animal
{
private:
double maxdeep; //km
public:
fish(): animal(), maxdeep(0.0) {}
fish(const fish& obj): animal(obj), maxdeep(obj.maxdeep) {}
fish(const string& _title, double _mass, double _speed, double _maxdeep):
animal(_title, _mass, _speed), maxdeep(_maxdeep) {}
fish() { cout << "fish deleted" << endl; }
protected:
// виртуальная функция _print переопределяется
// в классе fish
void _print() const
{
animal::_print();
cout << ", maxdeep: " << maxdeep;
}
};
int main()
{
setlocale(0, "Rus");
// создание объектов и вывод информации о них
animal("Паук", 0.003, 0.05).print();
bird("Ворона", 0.3, 10, 0.1).print();
fish("Рыба-молот", 150, 5, 0.5).print();
cout << endl;
system("pause");
return 0;
}
-
Виртуальные функции и абстрактные классы
Не всегда для базового класса можно определить поведение той или иной функции. Примеры этого можно найти в реальном мире, в частности, все животные в том или ином виде могут перемещаться: рыбы плавают, звери бегает, змеи ползают, птицы летают (упрощено для примера). Однако как именно перемещается некое абстрактное животное, сказать нельзя.
В подобных случаях С++ дает возможность не определять в базовом классе код виртуальной функции, такие функции определяются нулевым значением и называются чисто виртуальными, например:
virtual void fun() = 0;
Класс, в котором определена хотя бы одна чисто виртуальная функция, называется абстрактным. Следует отметить, что нельзя создать объект от абстрактного класса непосредственно. Объекты можно создавать только от тех его производных классов, в которых все чисто виртуальные функции переопределены.
Дополним приведенный выше пример:
#include
#include
using namespace std;
class creature
{
private:
string title;
double mass; //kg
protected:
// конструкторы вынесены в protected, т.к. нет необходимости создавать
// объекты непосредственно этого класса, однако, эти
// конструкторы должны быть доступны из производных классов
// аналогично вынесен деструктор
creature() :mass(0.0) {} // конструктор без параметров
// конструктор копирования
creature(const creature& obj) :title(obj.title), mass(obj.mass) {}
// конструктор с параметрами
creature(const string& _title, double _mass) : title(_title), mass(_mass) {}
// деструктор (объявлен как виртуальный)
virtual
creature() { cout << "creature deleted" << endl << endl; }
// защищенная виртуальная функция для вывода информации об объекте
// не должна использоваться вне данного класса и его производных
virtual void _print() const
{
cout << "title: " << title << endl;
cout << ", mass: " << mass << endl;
}
public:
// открытая функция для вывода информации об объекте
void print() const
{
// выводит название класса, к которому принадлежит
// объект, для которого она вызвана,
cout << typeid(*this).name() << ": (";
// и вызывает виртуальную функцию
// т.к. функция _print виртуальная, вызываться она
// будет не только из текущего класса, но и из производных,
// в зависимости от того, для какого объекта осуществляется вызов
_print();
cout << ")" << endl;
}
double get_mass() const { return mass; }
void set_mass(double new_mass) { mass = new_mass; }
};
// класс animal наследуется от класса creature
class animal : public creature
{
private:
double speed; // m/s
protected:
// конструкторы класса animal осуществляют вызовы
// конструкторов
// базового класса (creature)
animal() : creature(), speed(0.0) {}
animal(const animal& obj) : creature(obj), speed(obj.speed) {}
animal(const string& _title, double _mass, double _speed) : creature(_title, _mass), speed(_speed) {}
animal() { cout << "animal deleted" << endl; }
// виртуальная функция _print переопределяется в
// производном классе
void _print() const
{
creature::_print();
cout << ", speed: " << speed;
}
public:
double get_speed() const { return speed; }
};
// класс bird наследуется от класса animal
class bird : public animal
{
private:
double topfly; // km
public:
bird() : animal(), topfly(0.0) {}
bird(const bird& obj) : animal(obj), topfly(obj.topfly) {}
bird(const string& _title, double _mass, double _speed, double _topfly) :
animal(_title, _mass, _speed), topfly(_topfly) {}
bird() { cout << "bird deleted" << endl; }
protected:
// виртуальная функция _print переопределяется
// теперь уже в классе bird
void _print() const
{
animal::_print();
cout << ", topfly: " << topfly;
}
};
// класс fish наследуется от класса animal
class fish : public animal
{
private:
double maxdeep; //km
public:
fish() : animal(), maxdeep(0.0) {}
fish(const fish& obj) : animal(obj), maxdeep(obj.maxdeep) {}
fish(const string& _title, double _mass, double _speed, double _maxdeep) :
animal(_title, _mass, _speed), maxdeep(_maxdeep) {}
fish() { cout << "fish deleted" << endl; }
protected:
// виртуальная функция _print переопределяется в классе fish
void _print() const
{
animal::_print();
cout << ", maxdeep: " << maxdeep;
}
};
// объявление нового класса - хищник (predator)
// класс predator наследуется от animal
class predator : public animal
{
protected:
predator() {}
public:
predator() {}
8 ЛАБОРАТОРНАЯ РАБОТА № 8.
РАБОТА С РОДИТЕЛЬСКИМИ И ДОЧЕРНИМИ КЛАССАМИ
-
Общие рекомендации по работе с родительскими и дочерними классами
Цель лабораторной работы - освоение технологий программирования задач, работающих с родительскими и дочерними классами.
Класс, который наследуется другим классом, называется базовым или родительским. Класс, выполняющий наследование, называется производным или дочерним. При этом как у одного базового класса может быть несколько родительских (множественное наследование), так и у одного родительского класса может быть несколько базовых классов.
Спецификаторы доступа при наследовании
В С++ экземпляры класса разделяют в соответствии с правами доступа на следующие три категории: открытые (public), закрытые (private) и защищенные (protected).
Статус доступа к экземплярам производного класса зависит от того, с каким спецификатором доступа объявляется наследование базового класса. Общая форма наследования классов имеет следующий вид:
class имя_производного_класса: доступ имя_базового_класса
{
// код
};
Здесь доступ определяет, каким способом наследуется базовый класс. Спецификатор доступа может принимать одно из трех значений: private, protected, public. Если он не указан, то: подразумевается public для производных классов, объявленных через struct, и private – для объявленных через class.
Если спецификатор принимает значение public, то все открытые и защищенные экземпляры базового класса становятся соответственно открытыми и защищенными экземплярами производного класса.
Если указан protected, то все открытые и защищенные экземпляры базового класса становятся защищенными экземпляры производного класса.
Если указан private, то все открытые и защищенные экземпляры базового класса становятся закрытыми экземплярами производного класса.
Деструкторы производных классов
В деструкторе производного класса компилятор автоматически генерирует вызовы деструкторов его базовых классов.
Для удаления объекта производного класса следует сделать деструктор в базовых классах виртуальным с целью корректного вызова деструкторов при использовании оператора delete.
Передача параметров в базовый класс
Когда базовый класс имеет конструктор с аргументами, производные классы должны передавать базовому классу необходимые аргументы. Для этого используется расширенная форма конструкторов:
порожденный_конструктор(список_аргументов):
базовый1(список_аргументов1),
…,
базовыйN(список_аргументовN)
{
// код
}
Здесь под базовый1, …, базовыйN обозначены имена базовых классов. С помощью двоеточия конструктор производного класса отделяется от списка конструкторов базового класса. Списки аргументов, передаваемых в конструкторы базовых классов, могут состоять из констант, глобальных переменных или параметров конструктора производного класса.
Если конструкторы производных классов не вызываются в явном виде (как в примере выше), вместо них из базовых классов автоматически вызываются конструкторы без параметров. Кроме того, конструкторы без параметров автоматически вызываются при инициализации вместо указанных конструкторов с параметрами в случае, если имеет место виртуальное наследование (см. ниже).
Указатели и ссылки на производные классы
В общем случае указатель одного типа не может указывать на объект другого типа, однако в С++ указатель на базовый класс может указывать на объект производного класса. Ссылки на базовый класс могут быть использованы для ссылок на объект производного типа.
Виртуальные функции
Виртуальная функция – это функция, объявленная с ключевым словом virtual в базовом классе и переопределенная в производных классах.
Это означает, что при использовании объекта производного класса с помощью указателя или ссылки на него как на объект базового класса, виртуальная функция вызывается из того класса, посредством которого этот объект был создан. То есть, в одном и том же участке кода для разных объектов могут вызываться разные версии одной и той же виртуальной функции. Класс, содержащий хотя бы одну виртуальную функцию, называется полиморфным классом.
Для виртуальных функций существуют следующие правила:
– виртуальную функцию нельзя объявлять как static;
– спецификатор virtual необязателен (но желателен) при переопределении функции в производном классе.
-
Пример программы с виртуальными функциями
#include
#include
using namespace std;
class creature
{
private:
string title;
double mass;
public:
creature() :mass(0.0) {} // конструктор без параметров
// конструктор копирования
creature(const creature& obj):title(obj.title), mass(obj.mass){}
// конструктор с параметрами
creature(const string& _title, double _mass) : title(_title), mass(_mass) {}
// деструктор (объявлен как виртуальный)
virtual
creature() { cout << "creature deleted" << endl << endl; }
protected:
// защищенная виртуальная функция для вывода информации об объекте
// не должна использоваться вне данного класса и его производных
virtual void _print() const
{
cout << "title: " << title << endl;
cout << ", mass: " << mass << endl;
}
public:
// открытая функция для вывода информации об объекте
void print() const
{
// выводит название класса, к которому принадлежит
// объект, для которого она вызвана,
cout << typeid(*this).name() << ": (";
// и вызывает виртуальную функцию
// т.к. функция _print виртуальная, вызываться она
// будет не только из текущего класса, но и из производных,
// в зависимости от того, для какого объекта
// осуществляется вызов
_print();
cout << ")" << endl;
}
};
// класс animal наследуется от класса creature
class animal : public creature
{
private:
double speed; // m/s
public:
// конструкторы класса animal осуществляют вызовы
// конструкторов
// базового класса (creature)
animal(): creature(), speed(0.0) {}
animal(const animal& obj): creature(obj), speed(obj.speed) {}
animal(const string& _title, double _mass, double _speed): creature(_title, _mass), speed(_speed){}
animal() { cout << "animal deleted" << endl; }
protected:
// виртуальная функция _print переопределяется в
// производном классе
void _print() const
{
creature::_print();
cout << ", speed: " << speed;
}
};
// класс bird наследуется от класса animal
class bird : public animal
{
private:
double topfly; // km
public:
bird(): animal(), topfly(0.0) {}
bird(const bird& obj): animal(obj), topfly(obj.topfly){}
bird(const string& _title, double _mass, double _speed, double _topfly):
animal (_title, _mass, _speed), topfly(_topfly) {}
bird() { cout << "bird deleted" << endl; }
protected:
// виртуальная функция _print переопределяется
// теперь уже в классе bird
void _print() const
{
animal::_print();
cout << ", topfly: " << topfly;
}
};
// класс fish наследуется от класса animal
class fish : public animal
{
private:
double maxdeep; //km
public:
fish(): animal(), maxdeep(0.0) {}
fish(const fish& obj): animal(obj), maxdeep(obj.maxdeep) {}
fish(const string& _title, double _mass, double _speed, double _maxdeep):
animal(_title, _mass, _speed), maxdeep(_maxdeep) {}
fish() { cout << "fish deleted" << endl; }
protected:
// виртуальная функция _print переопределяется
// в классе fish
void _print() const
{
animal::_print();
cout << ", maxdeep: " << maxdeep;
}
};
int main()
{
setlocale(0, "Rus");
// создание объектов и вывод информации о них
animal("Паук", 0.003, 0.05).print();
bird("Ворона", 0.3, 10, 0.1).print();
fish("Рыба-молот", 150, 5, 0.5).print();
cout << endl;
system("pause");
return 0;
}
-
Виртуальные функции и абстрактные классы
Не всегда для базового класса можно определить поведение той или иной функции. Примеры этого можно найти в реальном мире, в частности, все животные в том или ином виде могут перемещаться: рыбы плавают, звери бегает, змеи ползают, птицы летают (упрощено для примера). Однако как именно перемещается некое абстрактное животное, сказать нельзя.
В подобных случаях С++ дает возможность не определять в базовом классе код виртуальной функции, такие функции определяются нулевым значением и называются чисто виртуальными, например:
virtual void fun() = 0;
Класс, в котором определена хотя бы одна чисто виртуальная функция, называется абстрактным. Следует отметить, что нельзя создать объект от абстрактного класса непосредственно. Объекты можно создавать только от тех его производных классов, в которых все чисто виртуальные функции переопределены.
Дополним приведенный выше пример:
#include
#include
using namespace std;
class creature
{
private:
string title;
double mass; //kg
protected:
// конструкторы вынесены в protected, т.к. нет необходимости создавать
// объекты непосредственно этого класса, однако, эти
// конструкторы должны быть доступны из производных классов
// аналогично вынесен деструктор
creature() :mass(0.0) {} // конструктор без параметров
// конструктор копирования
creature(const creature& obj) :title(obj.title), mass(obj.mass) {}
// конструктор с параметрами
creature(const string& _title, double _mass) : title(_title), mass(_mass) {}
// деструктор (объявлен как виртуальный)
virtual
creature() { cout << "creature deleted" << endl << endl; }
// защищенная виртуальная функция для вывода информации об объекте
// не должна использоваться вне данного класса и его производных
virtual void _print() const
{
cout << "title: " << title << endl;
cout << ", mass: " << mass << endl;
}
public:
// открытая функция для вывода информации об объекте
void print() const
{
// выводит название класса, к которому принадлежит
// объект, для которого она вызвана,
cout << typeid(*this).name() << ": (";
// и вызывает виртуальную функцию
// т.к. функция _print виртуальная, вызываться она
// будет не только из текущего класса, но и из производных,
// в зависимости от того, для какого объекта осуществляется вызов
_print();
cout << ")" << endl;
}
double get_mass() const { return mass; }
void set_mass(double new_mass) { mass = new_mass; }
};
// класс animal наследуется от класса creature
class animal : public creature
{
private:
double speed; // m/s
protected:
// конструкторы класса animal осуществляют вызовы
// конструкторов
// базового класса (creature)
animal() : creature(), speed(0.0) {}
animal(const animal& obj) : creature(obj), speed(obj.speed) {}
animal(const string& _title, double _mass, double _speed) : creature(_title, _mass), speed(_speed) {}
animal() { cout << "animal deleted" << endl; }
// виртуальная функция _print переопределяется в
// производном классе
void _print() const
{
creature::_print();
cout << ", speed: " << speed;
}
public:
double get_speed() const { return speed; }
};
// класс bird наследуется от класса animal
class bird : public animal
{
private:
double topfly; // km
public:
bird() : animal(), topfly(0.0) {}
bird(const bird& obj) : animal(obj), topfly(obj.topfly) {}
bird(const string& _title, double _mass, double _speed, double _topfly) :
animal(_title, _mass, _speed), topfly(_topfly) {}
bird() { cout << "bird deleted" << endl; }
8 ЛАБОРАТОРНАЯ РАБОТА № 8.
РАБОТА С РОДИТЕЛЬСКИМИ И ДОЧЕРНИМИ КЛАССАМИ
-
Общие рекомендации по работе с родительскими и дочерними классами
Цель лабораторной работы - освоение технологий программирования задач, работающих с родительскими и дочерними классами.
Класс, который наследуется другим классом, называется базовым или родительским. Класс, выполняющий наследование, называется производным или дочерним. При этом как у одного базового класса может быть несколько родительских (множественное наследование), так и у одного родительского класса может быть несколько базовых классов.
Спецификаторы доступа при наследовании
В С++ экземпляры класса разделяют в соответствии с правами доступа на следующие три категории: открытые (public), закрытые (private) и защищенные (protected).
Статус доступа к экземплярам производного класса зависит от того, с каким спецификатором доступа объявляется наследование базового класса. Общая форма наследования классов имеет следующий вид:
class имя_производного_класса: доступ имя_базового_класса
{
// код
};
Здесь доступ определяет, каким способом наследуется базовый класс. Спецификатор доступа может принимать одно из трех значений: private, protected, public. Если он не указан, то: подразумевается public для производных классов, объявленных через struct, и private – для объявленных через class.
Если спецификатор принимает значение public, то все открытые и защищенные экземпляры базового класса становятся соответственно открытыми и защищенными экземплярами производного класса.
Если указан protected, то все открытые и защищенные экземпляры базового класса становятся защищенными экземпляры производного класса.
Если указан private, то все открытые и защищенные экземпляры базового класса становятся закрытыми экземплярами производного класса.
Деструкторы производных классов
В деструкторе производного класса компилятор автоматически генерирует вызовы деструкторов его базовых классов.
Для удаления объекта производного класса следует сделать деструктор в базовых классах виртуальным с целью корректного вызова деструкторов при использовании оператора delete.
Передача параметров в базовый класс
Когда базовый класс имеет конструктор с аргументами, производные классы должны передавать базовому классу необходимые аргументы. Для этого используется расширенная форма конструкторов:
порожденный_конструктор(список_аргументов):
базовый1(список_аргументов1),
…,
базовыйN(список_аргументовN)
{
// код
}
Здесь под базовый1, …, базовыйN обозначены имена базовых классов. С помощью двоеточия конструктор производного класса отделяется от списка конструкторов базового класса. Списки аргументов, передаваемых в конструкторы базовых классов, могут состоять из констант, глобальных переменных или параметров конструктора производного класса.
Если конструкторы производных классов не вызываются в явном виде (как в примере выше), вместо них из базовых классов автоматически вызываются конструкторы без параметров. Кроме того, конструкторы без параметров автоматически вызываются при инициализации вместо указанных конструкторов с параметрами в случае, если имеет место виртуальное наследование (см. ниже).
Указатели и ссылки на производные классы
В общем случае указатель одного типа не может указывать на объект другого типа, однако в С++ указатель на базовый класс может указывать на объект производного класса. Ссылки на базовый класс могут быть использованы для ссылок на объект производного типа.
Виртуальные функции
Виртуальная функция – это функция, объявленная с ключевым словом virtual в базовом классе и переопределенная в производных классах.
Это означает, что при использовании объекта производного класса с помощью указателя или ссылки на него как на объект базового класса, виртуальная функция вызывается из того класса, посредством которого этот объект был создан. То есть, в одном и том же участке кода для разных объектов могут вызываться разные версии одной и той же виртуальной функции. Класс, содержащий хотя бы одну виртуальную функцию, называется полиморфным классом.
Для виртуальных функций существуют следующие правила:
– виртуальную функцию нельзя объявлять как static;
– спецификатор virtual необязателен (но желателен) при переопределении функции в производном классе.
-
Пример программы с виртуальными функциями
#include
#include
using namespace std;
class creature
{
private:
string title;
double mass;
public:
creature() :mass(0.0) {} // конструктор без параметров
// конструктор копирования
creature(const creature& obj):title(obj.title), mass(obj.mass){}
// конструктор с параметрами
creature(const string& _title, double _mass) : title(_title), mass(_mass) {}
// деструктор (объявлен как виртуальный)
virtual
creature() { cout << "creature deleted" << endl << endl; }
protected:
// защищенная виртуальная функция для вывода информации об объекте
// не должна использоваться вне данного класса и его производных
virtual void _print() const
{
cout << "title: " << title << endl;
cout << ", mass: " << mass << endl;
}
public:
// открытая функция для вывода информации об объекте
void print() const
{
// выводит название класса, к которому принадлежит
// объект, для которого она вызвана,
cout << typeid(*this).name() << ": (";
// и вызывает виртуальную функцию
// т.к. функция _print виртуальная, вызываться она
// будет не только из текущего класса, но и из производных,
// в зависимости от того, для какого объекта
// осуществляется вызов
_print();
cout << ")" << endl;
}
};
// класс animal наследуется от класса creature
class animal : public creature
{
private:
double speed; // m/s
public:
// конструкторы класса animal осуществляют вызовы
// конструкторов
// базового класса (creature)
animal(): creature(), speed(0.0) {}
animal(const animal& obj): creature(obj), speed(obj.speed) {}
animal(const string& _title, double _mass, double _speed): creature(_title, _mass), speed(_speed){}
animal() { cout << "animal deleted" << endl; }
protected:
// виртуальная функция _print переопределяется в
// производном классе
void _print() const
{
creature::_print();
cout << ", speed: " << speed;
}
};
// класс bird наследуется от класса animal
class bird : public animal
{
private:
double topfly; // km
public:
bird(): animal(), topfly(0.0) {}
bird(const bird& obj): animal(obj), topfly(obj.topfly){}
bird(const string& _title, double _mass, double _speed, double _topfly):
animal (_title, _mass, _speed), topfly(_topfly) {}
bird() { cout << "bird deleted" << endl; }
protected:
// виртуальная функция _print переопределяется
// теперь уже в классе bird
void _print() const
{
animal::_print();
cout << ", topfly: " << topfly;
}
};
// класс fish наследуется от класса animal
class fish : public animal
{
private:
double maxdeep; //km
public:
fish(): animal(), maxdeep(0.0) {}
fish(const fish& obj): animal(obj), maxdeep(obj.maxdeep) {}
fish(const string& _title, double _mass, double _speed, double _maxdeep):
animal(_title, _mass, _speed), maxdeep(_maxdeep) {}
fish() { cout << "fish deleted" << endl; }
protected:
// виртуальная функция _print переопределяется
// в классе fish
void _print() const
{
animal::_print();
cout << ", maxdeep: " << maxdeep;
}
};
int main()
{
setlocale(0, "Rus");
// создание объектов и вывод информации о них
animal("Паук", 0.003, 0.05).print();
bird("Ворона", 0.3, 10, 0.1).print();
fish("Рыба-молот", 150, 5, 0.5).print();
cout << endl;
system("pause");
return 0;
}
-
Виртуальные функции и абстрактные классы
Не всегда для базового класса можно определить поведение той или иной функции. Примеры этого можно найти в реальном мире, в частности, все животные в том или ином виде могут перемещаться: рыбы плавают, звери бегает, змеи ползают, птицы летают (упрощено для примера). Однако как именно перемещается некое абстрактное животное, сказать нельзя.
В подобных случаях С++ дает возможность не определять в базовом классе код виртуальной функции, такие функции определяются нулевым значением и называются чисто виртуальными, например:
virtual void fun() = 0;
Класс, в котором определена хотя бы одна чисто виртуальная функция, называется абстрактным. Следует отметить, что нельзя создать объект от абстрактного класса непосредственно. Объекты можно создавать только от тех его производных классов, в которых все чисто виртуальные функции переопределены.
Дополним приведенный выше пример:
#include
#include
using namespace std;
class creature
{
private:
string title;
double mass; //kg
protected:
// конструкторы вынесены в protected, т.к. нет необходимости создавать
// объекты непосредственно этого класса, однако, эти
// конструкторы должны быть доступны из производных классов
// аналогично вынесен деструктор
creature() :mass(0.0) {} // конструктор без параметров
// конструктор копирования
creature(const creature& obj) :title(obj.title), mass(obj.mass) {}
// конструктор с параметрами
creature(const string& _title, double _mass) : title(_title), mass(_mass) {}
// деструктор (объявлен как виртуальный)
virtual
creature() { cout << "creature deleted" << endl << endl; }
8 ЛАБОРАТОРНАЯ РАБОТА № 8.
РАБОТА С РОДИТЕЛЬСКИМИ И ДОЧЕРНИМИ КЛАССАМИ
-
Общие рекомендации по работе с родительскими и дочерними классами
Цель лабораторной работы - освоение технологий программирования задач, работающих с родительскими и дочерними классами.
Класс, который наследуется другим классом, называется базовым или родительским. Класс, выполняющий наследование, называется производным или дочерним. При этом как у одного базового класса может быть несколько родительских (множественное наследование), так и у одного родительского класса может быть несколько базовых классов.
Спецификаторы доступа при наследовании
В С++ экземпляры класса разделяют в соответствии с правами доступа на следующие три категории: открытые (public), закрытые (private) и защищенные (protected).
Статус доступа к экземплярам производного класса зависит от того, с каким спецификатором доступа объявляется наследование базового класса. Общая форма наследования классов имеет следующий вид:
class имя_производного_класса: доступ имя_базового_класса
{
// код
};
Здесь доступ определяет, каким способом наследуется базовый класс. Спецификатор доступа может принимать одно из трех значений: private, protected, public. Если он не указан, то: подразумевается public для производных классов, объявленных через struct, и private – для объявленных через class.
Если спецификатор принимает значение public, то все открытые и защищенные экземпляры базового класса становятся соответственно открытыми и защищенными экземплярами производного класса.
Если указан protected, то все открытые и защищенные экземпляры базового класса становятся защищенными экземпляры производного класса.
Если указан private, то все открытые и защищенные экземпляры базового класса становятся закрытыми экземплярами производного класса.
Деструкторы производных классов
В деструкторе производного класса компилятор автоматически генерирует вызовы деструкторов его базовых классов.
Для удаления объекта производного класса следует сделать деструктор в базовых классах виртуальным с целью корректного вызова деструкторов при использовании оператора delete.
Передача параметров в базовый класс
Когда базовый класс имеет конструктор с аргументами, производные классы должны передавать базовому классу необходимые аргументы. Для этого используется расширенная форма конструкторов:
порожденный_конструктор(список_аргументов):
базовый1(список_аргументов1),
…,
базовыйN(список_аргументовN)
{
// код
}
Здесь под базовый1, …, базовыйN обозначены имена базовых классов. С помощью двоеточия конструктор производного класса отделяется от списка конструкторов базового класса. Списки аргументов, передаваемых в конструкторы базовых классов, могут состоять из констант, глобальных переменных или параметров конструктора производного класса.
Если конструкторы производных классов не вызываются в явном виде (как в примере выше), вместо них из базовых классов автоматически вызываются конструкторы без параметров. Кроме того, конструкторы без параметров автоматически вызываются при инициализации вместо указанных конструкторов с параметрами в случае, если имеет место виртуальное наследование (см. ниже).
Указатели и ссылки на производные классы
В общем случае указатель одного типа не может указывать на объект другого типа, однако в С++ указатель на базовый класс может указывать на объект производного класса. Ссылки на базовый класс могут быть использованы для ссылок на объект производного типа.
Виртуальные функции
Виртуальная функция – это функция, объявленная с ключевым словом virtual в базовом классе и переопределенная в производных классах.
Это означает, что при использовании объекта производного класса с помощью указателя или ссылки на него как на объект базового класса, виртуальная функция вызывается из того класса, посредством которого этот объект был создан. То есть, в одном и том же участке кода для разных объектов могут вызываться разные версии одной и той же виртуальной функции. Класс, содержащий хотя бы одну виртуальную функцию, называется полиморфным классом.
Для виртуальных функций существуют следующие правила:
– виртуальную функцию нельзя объявлять как static;
– спецификатор virtual необязателен (но желателен) при переопределении функции в производном классе.
-
Пример программы с виртуальными функциями
#include
#include
using namespace std;
class creature
{
private:
string title;
double mass;
public:
creature() :mass(0.0) {} // конструктор без параметров
// конструктор копирования
creature(const creature& obj):title(obj.title), mass(obj.mass){}
// конструктор с параметрами
creature(const string& _title, double _mass) : title(_title), mass(_mass) {}
// деструктор (объявлен как виртуальный)
virtual
creature() { cout << "creature deleted" << endl << endl; }
protected:
// защищенная виртуальная функция для вывода информации об объекте
// не должна использоваться вне данного класса и его производных
virtual void _print() const
{
cout << "title: " << title << endl;
cout << ", mass: " << mass << endl;
}
public:
// открытая функция для вывода информации об объекте
void print() const
{
// выводит название класса, к которому принадлежит
// объект, для которого она вызвана,
cout << typeid(*this).name() << ": (";
// и вызывает виртуальную функцию
// т.к. функция _print виртуальная, вызываться она
// будет не только из текущего класса, но и из производных,
// в зависимости от того, для какого объекта
// осуществляется вызов
_print();
cout << ")" << endl;
}
};
// класс animal наследуется от класса creature
class animal : public creature
{
private:
double speed; // m/s
public:
// конструкторы класса animal осуществляют вызовы
// конструкторов
// базового класса (creature)
animal(): creature(), speed(0.0) {}
animal(const animal& obj): creature(obj), speed(obj.speed) {}
animal(const string& _title, double _mass, double _speed): creature(_title, _mass), speed(_speed){}
animal() { cout << "animal deleted" << endl; }
protected:
// виртуальная функция _print переопределяется в
// производном классе
void _print() const
{
creature::_print();
cout << ", speed: " << speed;
}
};
// класс bird наследуется от класса animal
class bird : public animal
{
private:
double topfly; // km
public:
bird(): animal(), topfly(0.0) {}
bird(const bird& obj): animal(obj), topfly(obj.topfly){}
bird(const string& _title, double _mass, double _speed, double _topfly):
animal (_title, _mass, _speed), topfly(_topfly) {}
bird() { cout << "bird deleted" << endl; } 8 ЛАБОРАТОРНАЯ РАБОТА № 8.
РАБОТА С РОДИТЕЛЬСКИМИ И ДОЧЕРНИМИ КЛАССАМИ
-
Общие рекомендации по работе с родительскими и дочерними классами
Цель лабораторной работы - освоение технологий программирования задач, работающих с родительскими и дочерними классами.
Класс, который наследуется другим классом, называется базовым или родительским. Класс, выполняющий наследование, называется производным или дочерним. При этом как у одного базового класса может быть несколько родительских (множественное наследование), так и у одного родительского класса может быть несколько базовых классов.
Спецификаторы доступа при наследовании
В С++ экземпляры класса разделяют в соответствии с правами доступа на следующие три категории: открытые (public), закрытые (private) и защищенные (protected).
Статус доступа к экземплярам производного класса зависит от того, с каким спецификатором доступа объявляется наследование базового класса. Общая форма наследования классов имеет следующий вид:
class имя_производного_класса: доступ имя_базового_класса
{
// код
};
Здесь доступ определяет, каким способом наследуется базовый класс. Спецификатор доступа может принимать одно из трех значений: private, protected, public. Если он не указан, то: подразумевается public для производных классов, объявленных через struct, и private – для объявленных через class.
Если спецификатор принимает значение public, то все открытые и защищенные экземпляры базового класса становятся соответственно открытыми и защищенными экземплярами производного класса.
Если указан protected, то все открытые и защищенные экземпляры базового класса становятся защищенными экземпляры производного класса.
Если указан private, то все открытые и защищенные экземпляры базового класса становятся закрытыми экземплярами производного класса.
Деструкторы производных классов
В деструкторе производного класса компилятор автоматически генерирует вызовы деструкторов его базовых классов.
Для удаления объекта производного класса следует сделать деструктор в базовых классах виртуальным с целью корректного вызова деструкторов при использовании оператора delete.
Передача параметров в базовый класс
Когда базовый класс имеет конструктор с аргументами, производные классы должны передавать базовому классу необходимые аргументы. Для этого используется расширенная форма конструкторов:
порожденный_конструктор(список_аргументов):
базовый1(список_аргументов1),
…,
базовыйN(список_аргументовN)
{
// код
}
Здесь под базовый1, …, базовыйN обозначены имена базовых классов. С помощью двоеточия конструктор производного класса отделяется от списка конструкторов базового класса. Списки аргументов, передаваемых в конструкторы базовых классов, могут состоять из констант, глобальных переменных или параметров конструктора производного класса.
Если конструкторы производных классов не вызываются в явном виде (как в примере выше), вместо них из базовых классов автоматически вызываются конструкторы без параметров. Кроме того, конструкторы без параметров автоматически вызываются при инициализации вместо указанных конструкторов с параметрами в случае, если имеет место виртуальное наследование (см. ниже).
Указатели и ссылки на производные классы
В общем случае указатель одного типа не может указывать на объект другого типа, однако в С++ указатель на базовый класс может указывать на объект производного класса. Ссылки на базовый класс могут быть использованы для ссылок на объект производного типа.
Виртуальные функции
Виртуальная функция – это функция, объявленная с ключевым словом virtual в базовом классе и переопределенная в производных классах.
Это означает, что при использовании объекта производного класса с помощью указателя или ссылки на него как на объект базового класса, виртуальная функция вызывается из того класса, посредством которого этот объект был создан. То есть, в одном и том же участке кода для разных объектов могут вызываться разные версии одной и той же виртуальной функции. Класс, содержащий хотя бы одну виртуальную функцию, называется полиморфным классом.
Для виртуальных функций существуют следующие правила:
– виртуальную функцию нельзя объявлять как static;
– спецификатор virtual необязателен (но желателен) при переопределении функции в производном классе.
-
Пример программы с виртуальными функциями
#include
#include
using namespace std;
class creature
{
private:
string title;
double mass;
public:
creature() :mass(0.0) {} // конструктор без параметров
// конструктор копирования
creature(const creature& obj):title(obj.title), mass(obj.mass){}
// конструктор с параметрами
creature(const string& _title, double _mass) : title(_title), mass(_mass) {}
// деструктор (объявлен как виртуальный)
virtual
creature() { cout << "creature deleted" << endl << endl; }-
Общие рекомендации по работе с родительскими и дочерними классами
-
Пример программы с виртуальными функциями
#include
using namespace std;
class creature
{
private:
string title;
double mass;
public:
creature() :mass(0.0) {} // конструктор без параметров
// конструктор копирования
creature(const creature& obj):title(obj.title), mass(obj.mass){}
// конструктор с параметрами
creature(const string& _title, double _mass) : title(_title), mass(_mass) {}
// деструктор (объявлен как виртуальный)
virtual
protected:
// защищенная виртуальная функция для вывода информации об объекте
// не должна использоваться вне данного класса и его производных
virtual void _print() const
{
cout << "title: " << title << endl;
cout << ", mass: " << mass << endl;
}
public:
// открытая функция для вывода информации об объекте
void print() const
{
// выводит название класса, к которому принадлежит
// объект, для которого она вызвана,
cout << typeid(*this).name() << ": (";
// и вызывает виртуальную функцию
// т.к. функция _print виртуальная, вызываться она
// будет не только из текущего класса, но и из производных,
// в зависимости от того, для какого объекта
// осуществляется вызов
_print();
cout << ")" << endl;
}
};
// класс animal наследуется от класса creature
class animal : public creature
{
private:
double speed; // m/s
public:
// конструкторы класса animal осуществляют вызовы
// конструкторов
// базового класса (creature)
animal(): creature(), speed(0.0) {}
animal(const animal& obj): creature(obj), speed(obj.speed) {}
animal(const string& _title, double _mass, double _speed): creature(_title, _mass), speed(_speed){}
protected:
// виртуальная функция _print переопределяется
// теперь уже в классе bird
void _print() const
{
animal::_print();
cout << ", topfly: " << topfly;
}
};
// класс fish наследуется от класса animal
class fish : public animal
{
private:
double maxdeep; //km
public:
fish(): animal(), maxdeep(0.0) {}
fish(const fish& obj): animal(obj), maxdeep(obj.maxdeep) {}
fish(const string& _title, double _mass, double _speed, double _maxdeep):
animal(_title, _mass, _speed), maxdeep(_maxdeep) {}
-
Виртуальные функции и абстрактные классы
#include
using namespace std;
class creature
{
private:
string title;
double mass; //kg
protected:
// конструкторы вынесены в protected, т.к. нет необходимости создавать
// объекты непосредственно этого класса, однако, эти
// конструкторы должны быть доступны из производных классов
// аналогично вынесен деструктор
creature() :mass(0.0) {} // конструктор без параметров
// конструктор копирования
creature(const creature& obj) :title(obj.title), mass(obj.mass) {}
// конструктор с параметрами
creature(const string& _title, double _mass) : title(_title), mass(_mass) {}
// деструктор (объявлен как виртуальный)
virtual
// защищенная виртуальная функция для вывода информации об объекте
// не должна использоваться вне данного класса и его производных
virtual void _print() const
{
cout << "title: " << title << endl;
cout << ", mass: " << mass << endl;
}
public:
// открытая функция для вывода информации об объекте
void print() const
{
// выводит название класса, к которому принадлежит
// объект, для которого она вызвана,
cout << typeid(*this).name() << ": (";
// и вызывает виртуальную функцию
// т.к. функция _print виртуальная, вызываться она
// будет не только из текущего класса, но и из производных,
// в зависимости от того, для какого объекта осуществляется вызов
_print();
cout << ")" << endl;
}
double get_mass() const { return mass; }
void set_mass(double new_mass) { mass = new_mass; }
};
// класс animal наследуется от класса creature
class animal : public creature
{
private:
double speed; // m/s
protected:
// конструкторы класса animal осуществляют вызовы
// конструкторов
// базового класса (creature)
animal() : creature(), speed(0.0) {}
animal(const animal& obj) : creature(obj), speed(obj.speed) {}
animal(const string& _title, double _mass, double _speed) : creature(_title, _mass), speed(_speed) {}
protected:
// виртуальная функция _print переопределяется
// теперь уже в классе bird
void _print() const
{
animal::_print();
cout << ", topfly: " << topfly;
}
};
// класс fish наследуется от класса animal
class fish : public animal
{
private:
double maxdeep; //km
public:
fish() : animal(), maxdeep(0.0) {}
fish(const fish& obj) : animal(obj), maxdeep(obj.maxdeep) {}
fish(const string& _title, double _mass, double _speed, double _maxdeep) :
animal(_title, _mass, _speed), maxdeep(_maxdeep) {}
// виртуальная функция hunt
// будет определять посредством производных классов,
// удастся ли хищнику поохотиться на жертву (obj)
virtual bool hunt(const animal& obj) = 0;
// т.к. hunt в данном классе - виртуальная,
// класс predator является абстрактным
};
// класс орел (eagle) наследуется от bird и predator
// (множественное наследование), т.к. орел - и птица, и хищник
class eagle : public bird, public predator
{
public:
eagle() : bird() {}
eagle(const eagle& obj) : bird(obj) {}
eagle(double _mass, double _speed, double _topfly)
:bird("Орел", _mass, _speed, _topfly) {}
// определение тела функции hunt
// т.к. hunt определена, класс eagle - Неабстрактный
bool hunt(const animal& obj)
{
// т.к. функция get_mass может наследоваться классом eagle
// из класса animal и через класс bird, и через класс predator
// укажем, что она наследуется через bird
return obj.get_mass() < bird::get_mass() &&
obj.get_speed() < bird::get_speed();
}
};
int main()
{
setlocale(0, "Rus");
bird raven("Ворона", 0.3, 10, 0.1);
eagle eagle1(1, 100, 1);
fish hammerhead("Рыба-молот", 150, 5, 0.5);
raven.print();
hammerhead.print();
cout << "Eagle vs raven: " << eagle1.hunt(raven) << endl;
cout << "Eagle vs hammerhead: " << eagle1.hunt(hammerhead) << endl;
cout << endl;
system("pause");
return 0;}
-
Задания к лабораторной работе № 8
Задание
При выполнении данной работы необходимо определить базовый класс и производные от него классы. Предусмотреть использование виртуальных функций.
Требуется создать абстрактный базовый класс, определить общие методы print(), get(), set() и, при необходимости, специфические для каждого производного класса методы. Создать набор производных классов. Заполнить их значениями. Вызывая виртуальные функции для экземпляров классов убедиться, что при одной и той же сигнатуре вызова – каждый раз отрабатывает нужный в данном случае экземпляр виртуальной функции.
Для того, чтобы протестировать каждый класс в программе, нужно сделать следующее:
– создать объект класса с использованием конструктора без параметров (все параметры потом установить с помощью методов set());
– создать объект с использованием конструктора с параметрами;
– создать объект с использованием конструктора копирования (потом поменять часть значений полей объекта с использованием методов set();
– вывести на экран созданные объекты с использованием метода print();
– вывести на экран созданные объекты в виде таблицы, используя методы get().
Отчет
Отчет должен содержать титульный лист, вариант задания, текст программы с комментариями, скриншоты результатов работы программы.
Варианты заданий
Вариант № 1
Базовый класс – «Транспорт», производные классы «Поезд», «Автобус», «Корабль».
Поля базового класса:
– название;
– количество мест.
Дополнительные поля класса «Автобус»:
– номер маршрута (тип string);
– скорость.
Дополнительные поля класса «Поезд»:
– номер поезда;
– количество вагонов.
Дополнительные поля класса «Корабль»:
– водоизмещение;
– число кают;
– скорость.
Вариант № 2
Базовый класс – «Устройства», производные классы «Память», «Диск», «Процессор».
Поля базового класса:
– тип устройства;
– количество на складе.
Дополнительные поля класса «Память»:
– тип памяти (например, DDR3 SDRAM, DDR4 SDRAM, DDR5 SDRAM);
– тактовая частота шины (возможные значения находятся в интервале от 800 до 8400 МГц;
Дополнительные поля класса «Диск»:
- интерфейс (стандарт обмена данными), возможные значения - ATA (IDE, PATA), SATA;
– объем данных в ГБ или ТБ.
Дополнительные поля класса «Процессор»:
– тактовая частота в МГц;
– разрядность (32/64 бит);
– скорость.
Вариант № 3
Базовый класс – «Устройства», производные классы «Клавиатура», «Мышь», «Монитор».
Поля базового класса:
– тип устройства;
– цена.
Дополнительные поля класса «Клавиатура»:
– количество кнопок (стандартное – 105, нестандартное);
– тип клавиатуры (мембранная, механическая).
Дополнительные поля класса «Мышь»:
– тип (механическая, оптическая, дистанционная);
– разъем для подключения (к порту РС/2, USB-порту).
Дополнительные поля класса «Монитор»:
– модель;
– длина диагонали;
- разрешение.
Вариант № 4
Базовый класс – «Устройства», производные классы «Принтер», «Видеокарта», «Сканер».
Поля базового класса:
– тип устройства;
– цена;
- количество на складе.
Дополнительные поля класса «Принтер»:
– модель принтера;
– скорость печати в стр./мин.
Дополнительные поля класса «Видеокарта»:
– объем видеопамяти в Mb, или Gb;
– тип видеопамяти (возможные значения - GDDR2, GDDR3, GDDR4 или GDDR5).
Дополнительные поля класса «Сканер»:
– оптическое разрешение, возможные значения - от 600 dpi до 1200 dpi;
– скорость сканирования (страниц в минуту).
Вариант № 5
Базовый класс – «Гарнитуры», производные классы «Прихожая», «Спальня», «Кухня».
Поля базового класса:
– название;
– цена;
- количество на складе.
Дополнительные поля класса «Прихожая»:
– цвет;
– длина.
Дополнительные поля класса «Спальня»:
– количество предметов;
– ширина кровати.
Дополнительные поля класса «Кухня»:
– материал;
– длина-высота.
Вариант № 6
Базовый класс – «Мебель», производные классы «Стул», «Стол», «Шкаф».
Поля базового класса:
– название;
– цена;
- количество на складе.
Дополнительные поля класса «Стул»:
– цвет;
– материал.
Дополнительные поля класса «Стол»:
– ширина;
– длина.
Дополнительные поля класса «Шкаф»:
– ширина;
– длина;
- высота.
Вариант № 7
Базовый класс – «Геометрическая фигура», производные классы «Прямоугольник», «Окружность», «Эллипс».
Поля базового класса:
– название;
– единица измерения размера.
Дополнительные поля класса «Прямоугольник»:
– длина;
– ширина.
Дополнительные поля класса «Окружность»:
– радиус.
Дополнительные поля класса «Эллипс»:
– большая ось;
- малая ось.
Вариант № 8
Базовый класс – «Автомобиль», производные классы «Легковой автомобиль», «Автобус», «Самосвал».
Поля базового класса:
– название;
– цена;
- марка бензина.
Дополнительные поля класса «Легковой автомобиль»:
– модель;
– цвет.
Дополнительные поля класса «Автобус»:
– номер маршрута;
– количество мест.
Дополнительные поля класса «Самосвал»:
– грузоподъемность;
- мощность двигателя.
Вариант № 9
Базовый класс – «Мыло», производные классы «Детское мыло», «Хозяйственное мыло», «Жидкое мыло».
Поля базового класса:
– название;
– цена;
- производитель.
Дополнительные поля класса «Детское мыло»:
– травяная добавка (возможные значения – нет, чистотел, череда, ромашка);
- вес в г.
Дополнительные поля класса «Хозяйственное мыло»:
– процент жирности;
– срок хранения.
Дополнительные поля класса «Жидкое мыло»:
– наполнитель запаха (сирень, роза и т.д.);
- объем в мл.
Вариант № 10
Базовый класс – «Канцтовары», производные классы «Тетради», «Карандаши», «Фломастеры».
Поля базового класса:
– название;
– цена.
Дополнительные поля класса «Тетради»:
– количество страниц;
- оформление (в линейку, в клетку).
Дополнительные поля класса «Карандаши»:
– мягкость или твердость (возможные значения - Т, М, ТМ);
– цвет.
Дополнительные поля класса «Фломастеры»:
– количество цветов;
- назначение (для бумаги, для доски).
Вариант № 11
Базовый класс – «Моющие средства», производные классы «Стиральные порошки», «Чистящие средства», «Для мытья посуды».
Поля базового класса:
– название;
– цена.
Дополнительные поля класса «Стиральные порошки»:
– вес в г;
- производитель.
Дополнительные поля класса «Чистящие средства»:
– дата изготовления;
– присутствие хлора (нет, есть).
Дополнительные поля класса «Для мытья посуды»:
– наполнитель (ромашка, яблоко и т.д.);
- объем в мл.
Вариант № 12
Базовый класс – «Книги», производные классы «Учебники», «Детективы», «Мемуары».
Поля базового класса:
– название;
– цена;
- авторы.
Дополнительные поля класса «Учебники»:
– раздел знаний (например, математика, программирование и т.д.);
- подраздел знаний (для математики: алгебра, математический анализ, вычислительная математика и т.д.; для программирования: язык С++, язык C#, язык Java и т.д.).
Дополнительные поля класса «Детективы»:
– вид (отечественный, переводной);
– издательство.
Дополнительные поля класса «Мемуары»:
– тематика (например, военные, исторические, личные и т.д.);
- год издания.
Вариант № 13
Базовый класс – «Электронные устройства», производные классы «Транзисторы», «Диоды», «Усилители».
Поля базового класса:
– название;
– цена;
- количество на складе.
Дополнительные поля класса «Транзисторы»:
– мощность коллектора (например, 30, 35, 50, 60 и т.д.);
- материал (например: Ge, Si).
Дополнительные поля класса «Диоды»:
– обратное напряжение (например: 10, 25, 75, 300 и т.д.);
– прямой ток (например: 20, 50, 100, 250 и т.д.).
Дополнительные поля класса «Усилители»:
– напряжение питания (например: 2х(5…20), 2х(7…40));
- коэффициент усиления (например: 30, 35, 50, 100, 500).
Вариант № 14
Базовый класс – «Коммуникационное оборудование», производные классы «Коммутаторы», «Маршрутизаторы».
Поля базового класса:
– название;
- производитель;
- количество на складе;
- цена.
Дополнительные поля класса «Коммутаторы»:
– скорость фильтрации кадров (количество кадров в секунду);
- максимальная длина кадра (например, 100-1500 байт);
- пропускная способность (5-10 Мб/с);
- задержка передачи кадра (от 10-40 мкс до 500 мкс).
Дополнительные поля класса «Маршрутизаторы»:
- перечень поддерживаемых сетевых протоколов (IP, CONS, CLNS OSI, IPX и т.д.);