Программирование. Принципы и практика использования C++ Исправленное издание, стр. 354
}Если мы инициализируем объект класса
Array_refPolygon[10]Shape*Мы решили проявить осторожность в отношении нулевых указателей (поскольку это обычный источник проблем) и пустых векторов.
template<class T> Array_ref<T> make_ref(vector<T>& v){ return (v.size()) ? Array_ref<T>(&v[0],v.size()):Array_ref<T>(0,0);}Идея заключается в том, чтобы передавать вектор элементов. Мы выбрали класс
vectorArray_refВ заключение предусмотрим обработку встроенных массивов в ситуациях, в которых компилятор знает их размер.
template <class T, int s> Array_ref<T> make_ref(T (&pp)[s]){ return Array_ref<T>(pp,s);}Забавное выражение
T(&pp)[s]ppsTArray_refPolygon ar[0]; // ошибка: элементов нетИспользуя данный вариант класса
Array_refvoid better(Array_ref<Shape> a){ for (int i = 0; i<a.size(); ++i) a[i].draw();}void f(Shape* q, vector<Circle>& s0){ Polygon s1[10]; Shape s2[20]; // инициализация Shape* p1 = new Rectangle(Point(0,0),Point(10,20)); better(make_ref(s0)); // ошибка: требуется Array_ref<Shape> better(make_ref(s1)); // ошибка: требуется Array_ref<Shape> better(make_ref(s2)); // OK (преобразование не требуется) better(make_ref(p1,1)); // OK: один элемент delete p1; p1 = 0; better(make_ref(p1,1)); // OK: нет элементов better(make_ref(q,max)); // OK (если переменная max задана корректно)}Мы видим улучшения.
• Код стал проще. Программисту редко приходится заботиться о размерах объектов, но когда это приходится делать, они задаются в специальном месте (при создании объекта класса
Array_ref• Проблема с типами, связанная с преобразованиями
Circle[]Shape[]Polygon[]Shape[]• Проблемы с неправильным количеством элементов объектов
s1s2• Потенциальная проблема с переменной max (и другими счетчиками элементов, необходимыми для использования указателей) становится явной — это единственное место, где мы должны явно указать размер.
• Использование нулевых указателей и пустых векторов предотвращается неявно и систематически.
25.4.4. Наследование и контейнеры
Что делать, если мы хотим обрабатывать коллекцию объектов класса
CircleShapebetter()draw_all()vector<Circle>vector<Shape>Array_ref<Circle>Array_ref<Shape>
a[i].draw()better()–>Что нам делать? Во-первых, мы должны работать с указателями (или ссылками), а не с самими объектами, поэтому следует попытаться использовать классы
Array_ref<Circle*>Array_ref<Shape*>Array_ref<Circle>Array_ref<Shape>Однако мы по-прежнему не можем конвертировать класс
Array_ref<Circle*>Array_ref<Shape*>Array_ref<Shape*>Circle*