Программирование. Принципы и практика использования C++ Исправленное издание - Бьёрн Страуструп
Книгу Программирование. Принципы и практика использования C++ Исправленное издание - Бьёрн Страуструп читаем онлайн бесплатно полную версию! Чтобы начать читать не надо регистрации. Напомним, что читать онлайн вы можете не только на компьютере, но и на андроид (Android), iPhone и iPad. Приятного чтения!
Шрифт:
Интервал:
Закладка:
19.3.3. Контейнеры и наследование
Это одна из разновидностей сочетания объектно-ориентированного и обобщенного программирования, которое люди постоянно, но безуспешно пытаются применять: использование контейнера объектов производного класса в качестве контейнера объектов базового класса. Рассмотрим пример.
vector<Shape> vs;
vector<Circle> vc;
vs = vc; // ошибка: требуется класс vector<Shape>
void f(vector<Shape>&);
f(vc); // ошибка: требуется класс vector<Shape>

Итак, попытаемся снова использовать указатели.
vector<Shape*> vps;
vector<Circle*> vpc;
vps = vpc; // ошибка: требуется класс vector<Shape*>
void f(vector<Shape*>&);
f(vpc); // ошибка: требуется класс vector<Shape*>
И вновь система типов сопротивляется. Почему? Рассмотрим, что может делать функция f().
void f(vector<Shape*>& v)
{
v.push_back(new Rectangle(Point(0,0),Point(100,100)));
}

19.3.4. Целые типы как шаблонные параметры

Рассмотрим пример наиболее распространенного использования целочисленного значения в качестве шаблонного аргумента: контейнер, количество элементов которого известно уже на этапе компиляции.
template<class T, int N> struct array {
T elem[N]; // хранит элементы в массиве -
// члене класса, использует конструкторы по умолчанию,
// деструктор и присваивание
T& operator[] (int n); // доступ: возвращает ссылку
const T& operator[] (int n) const;
T* data() { return elem; } // преобразование в тип T*
const T* data() const { return elem; }
int size() const { return N; }
}
Мы можем использовать класс array (см. также раздел 20.7) примерно так:
array<int,256> gb; // 256 целых чисел
array<double,6> ad = { 0.0, 1.1, 2.2, 3.3, 4.4, 5.5 }; // инициализатор!
const int max = 1024;
void some_fct(int n)
{
array<char,max> loc;
array<char,n> oops; // ошибка: значение n компилятору
// неизвестно
// ...
array<char,max> loc2 = loc; // создаем резервную копию
// ...
loc = loc2; // восстанавливаем
// ...
}
Ясно, что класс array очень простой — более простой и менее мощный, чем класс vector, — так почему иногда следует использовать его, а не класс vector? Один из ответов: “эффективность”. Размер объекта класса array известен на этапе компиляции, поэтому компилятор может выделить статическую память (для глобальных объектов, таких как gb) или память в стеке (для локальных объектов, таких как loc), а не свободную память. Проверяя выход за пределы диапазона, мы сравниваем константы (например, размер N). Для большинства программ это повышение эффективности незначительно, но если мы создаем важный компонент системы, например драйвер сети, то даже небольшая разница оказывается существенной. Что еще более важно, некоторые программы просто не могут использовать свободную память. Такие программы обычно работают во встроенных системах и/или в программах, для которых основным критерием является безопасность (подробно об этом речь пойдет в главе 25). В таких программах массив array имеет много преимуществ над классом vector без нарушения основного ограничения (запрета на использование свободной памяти).
Поставим противоположный вопрос: “Почему бы просто не использовать класс vector?”, а не “Почему бы просто не использовать встроенные массивы?” Как было показано в разделе 18.5, массивы могут порождать ошибки: они не знают своего размера, они конвертируют указатели при малейшей возможности и неправильно копируются; в классе array, как и в классе vector, таких проблем нет. Рассмотрим пример.
double* p = ad; // ошибка: нет неявного преобразования
// в указатель
double* q = ad.data(); // OK: явное преобразование
template<class C> void printout(const C& c) // шаблонная функция
{
for (int i = 0; i<c.size(); ++i) cout << c[i] <<'n';
Эту функцию printout() можно вызвать как в классе array, так и в классе vector.
printout(ad); // вызов из
Прочитали книгу? Предлагаем вам поделится своим отзывом от прочитанного(прослушанного)! Ваш отзыв будет полезен читателям, которые еще только собираются познакомиться с произведением.
Уважаемые читатели, слушатели и просто посетители нашей библиотеки! Просим Вас придерживаться определенных правил при комментировании литературных произведений.
- 1. Просьба отказаться от дискриминационных высказываний. Мы защищаем право наших читателей свободно выражать свою точку зрения. Вместе с тем мы не терпим агрессии. На сайте запрещено оставлять комментарий, который содержит унизительные высказывания или призывы к насилию по отношению к отдельным лицам или группам людей на основании их расы, этнического происхождения, вероисповедания, недееспособности, пола, возраста, статуса ветерана, касты или сексуальной ориентации.
- 2. Просьба отказаться от оскорблений, угроз и запугиваний.
- 3. Просьба отказаться от нецензурной лексики.
- 4. Просьба вести себя максимально корректно как по отношению к авторам, так и по отношению к другим читателям и их комментариям.
Надеемся на Ваше понимание и благоразумие. С уважением, администратор knigkindom.ru.
Оставить комментарий
-
Гость Татьяна24 сентябрь 22:20 Как то не очень... Невеста по ошибке. Я не дам тебе развод - Майя Линн
-
Римма24 сентябрь 21:52 Почему главные героинитпкие идиотки? И сюжет не плохой, и написано хорошо. Но как героиня - так дура дурой.... Хозяйка маленького дома, или Любимая для дракона - Кира Рамис
-
Римма20 сентябрь 12:27 Много ненужных пояснений и отступлений. Весь сюжет теряет свою привлекательность. Героиня иногда так тупит, что читать не... Хозяйка приюта для перевертышей и полукровок - Елена Кутукова