Производные классы
Теперь давайте определим вектор, для которого пользователь может задавать границы изменения индекса.
class vec: public vector { int low, high; public: vec(int,int); int elem(int); int operator[](int); };
Определение vec как
:public vector
означает, в первую очередь, что vec это vector. То есть, тип vec имеет (наследует) все свойства типа vector дополнительно к тем, что описаны специально для него. Говорят, что класс vector является базовым классом для vec, а о vec говорится, что он производный от vector.
Класс vec модифицирует класс vector тем, что в нем задается другой конструктор, который требует от пользователя указывать две границы изменения индекса, а не длину, и имеются свои собственные функции доступа elem(int) и operator[](int). Функция elem() класса vec легко выражается через elem() класса vector:
int vec::elem(int i) { return vector::elem(i-low); }
Операция разрешения области видимости :: используется для того, чтобы не было бесконечной рекурсии обращения к vec::elem() из нее самой. с помощью унарной операции :: можно ссылаться на нелокальные имена. Было бы разумно описать vec::elem() как inline, поскольку, скорее всего, эффективность существенна, но необязательно, неразумно и невозможно написать ее так, чтобы она непосредственно использовала закрытый член v класса vector. Фунции производного класса не имеют специального доступа к закрытым членам его базового класса.
Конструктор можно написать так:
vec::vec(int lb, int hb) : (hb-lb+1) { if (hb-lb
Запись : (hb-lb+1) используется для определения списка параметров конструктора базового класса vector::vector(). Этот конструктор вызывается перед телом vec::vec(). Вот небольшой пример, который можно запустить, если скомпилировать его вместе с остальными описаниями vector:
#include
void error(char* p) { cerr
Не надо размножать объекты без необходимости - У. Оккам
В этой главе описывается понятие производного класса в C++. Производные классы дают простой, гибкий и эффективный аппарат задания для класса альтернативного интерфейса и определения класса посредством добавления возможностей к уже имеющемуся классу без перепрограммирования или перекомпиляции. С помощью производных классов можно также обеспечить общий интерфейс для нескольких различных классов так, чтобы другие части программы могли работать с объектами этих классов одинаковым образом. При этом обычно в каждый объект помещается информация о типе, чтобы эти объекты могли обрабатываться соответствующим образом в ситуациях, когда их тип нельзя узнать во время компиляции. Для элегантной и надежной обработки таких динамических зависимостей типов имеется понятие виртуальной функции. По своей сути производные классы существуют для того, чтобы облегчить программисту формулировку общности.
В конструкции
агрег идентификатор:public opt typedef-имя
typedef-имя должно означать ранее описанный класс, называемый базовым классом для класса, подлежащего описанию. Говорится, что последний выводится из предшествующего. На члены базового класса можно ссылаться, как если бы они были членами производного класса, за исключением тех случаев, когда имя базового члена было переопределено в производном классе; в этом случае для ссылки на скрытое имя может использоваться такая запись (#7.1):
typedef-имя :: идентификатор
Например:
struct base { int a; int b; };
struct derived : public base { int b; int c; };
derived d;
d.a = 1; d.base::b = 2; d.b = 3; d.c = 4;
осуществляет присваивание четырем членам d.
Производный тип сам может использоваться как базовый.