Введение в язык Си++

         

Полиморфные Вектора


У вас есть другая возможность - определить ваш векторный и другие вмещающие классы через указатели на объекты некоторого класса:

class common { //... }; class vector { common** v; //... public: cvector(int); common* elem(int); common* operator[](int); //... };

Заметьте, что поскольку в таких векторах хранятся указатели, а не сами объекты, объект может быть "в" нескольких таких векторах одновременно. Это очень полезное свойство подобных вмещающих классов, таких, как вектора, связанные списки, множества и т.д. Кроме того, можно присваивать указатель на производный класс указателю на его базовый класс, поэтому можно использовать приведенный выше cvector для хранения указателей на объекты всех производных от common классов. Например:

class apple : public common { /*...*/ } class orange : public common { /*...*/ } class apple_vector : public cvector { public:

cvector fruitbowl(100); //... apple aa; orange oo; //... fruitbowl[0] = aa fruitbowl[1] = oo }

Однако, точный тип объекта, вошедшего в такой вмещающий класс, больше компилятору не известен. Например, в предыдущем примере вы знаете, что элемент вектора является common, но является он apple или orange? Обычно точный тип должен в последствие быть восстановлен, чтобы обеспечить правильное использование объекта. Для этого нужно или в какой-то форме хранить информацию о типе в самом объекте, или обеспечить, чтобы во вмещающий класс помещались только объекты данного типа. Последнее легко достигается с помощью производного класса. Вы можете, например, создать вектор указателей на apple:

class apple_vector : public cvector { public: apple* elem(int i) { return (apple*) cvector::elem(i); } //... };

используя запись приведения к типу (тип)выражение, чтобы преобразовать common* (ссылку на указатель на common), которую возвращает cvector::elem, в apple*. Такое применение производных классов создает альтернативу обобщенным классам. Писать его немного труднее (если не использовать макросы таким образом, чтобы производные классы фактически реализовывали обобщенные классы; см. ), но оно имеет то преимущество, что все производные классы совместно используют единственную копию функции базового класса. В случае обобщенных классов, таких, как vector(type), для каждого нового используемого типа должна создаваться (с помощью implement()) новая копия таких функций. Другой способ, хранение идентификации типа в каждом объекте, приводит нас к стилю программирования, который часто называют объекто-основанным или объектно-ориентированным.



Содержание раздела