Файл: Лабораторная работа работа с родительскими и дочерними классами.docx
ВУЗ: Не указан
Категория: Не указан
Дисциплина: Не указана
Добавлен: 02.12.2023
Просмотров: 132
Скачиваний: 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// укажем, что она наследуется через birdreturn 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
Отчет должен содержать титульный лист, вариант задания, текст программы с комментариями, скриншоты результатов работы программы.Варианты заданийВариант № 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 и т.д.);