|
Программирование >> Решение нетривиальных задач
operator int ( void); operator const char * ( void); то простой оператор, подобный: some class x; cout << x; не сработает. Проблема в том, что класс stream определяет те же два преобразования: ostream &ostream:: operator<<( int x ); ostream &ostream:: operator<<( const char *s ); Так как имеется два варианта преобразований, то компилятор не знает, какой из них выбрать. Лучше выполнять все преобразования типов при помощи конструкторов и определять минимально необходимый их набор. Например, если у вас есть преобразование из типа double, то вам не нужны int, long и так далее, потому что нормальные правила преобразования типов Си применяются компилятором при вызове вашего конструктора. Управление памятью 219 Часть 8ж. Управление памятью 152. Используйте new/delete вместо malloc()/free() Нет гарантии, что оператор new() вызывает malloc() при запросе памяти для себя. Он может реализовывать свою собственную функцию управления памятью. Следовательно, возникает трудно обнаруживаемая ошибка при передаче функцией free() памяти, полученной при помощи new (и наоборот). Избегайте неприятностей, используя всегда при работе с Си++ new и delete. Наряду с прочим, это означает, что вы не должны пользоваться strdup() или любой другой функцией, скрывающей вызов malloc(). 153. Вся память, выделенная в конструкторе, должна быть освобождена в деструкторе Невыполнение этого обычно приводит к ошибке, но я видел программу, где это делалось намеренно. Упомянутая программа на самом деле нарушала другое правило: Не позволяй открытого доступа к закрытому классу . Функция-член не только возвращала внутренний указатель на память, выделенную new, но класс ожидал, что вызывающая функция передает этот указатель delete. Это плохая идея со всех сторон: получить при этом утечку памяти - значит легко отделаться. С точки зрения поиска ошибок помогает близкое физическое расположение конструктора и деструктора рядом друг с другом в файле .cpp, чтобы сделать их заметнее при отладке. 154. Локальные перегрузки операторов new и delete опасны Здесь основной проблемой является то, что операторы new и delete, определенные в виде членов класса, следуют другим правилам, чем перегруженные на глобальном уровне. Локальная перегрузка используется лишь тогда, когда вы размещаете единственный объект. Глобальная перегрузка используется вами всегда при размещении массива. Следовательно, этот код, скорее всего, не будет работать: some class *p = new some class[1]; вызывает глобальн1й оператор new() ... delete p; вызывает some class::operator delete() Помните, что эти две строки могут быть в различных файлах. Часть 8з. Шаблоны Многие проблемы с шаблонами в действительности вызваны учебниками, которые обычно настолько упрощенно рассматривают шаблоны, что вы заканчиваете чтение, не получив и намека на то, как они должны использоваться. Этот раздел посвящен распространенным затруднениям, связанным с шаблонами. 155. Используйте встроенные шаблоны функций вместо параметризированных макросов Приведенный ранее пример: #define SQUARE(x) ((x) * (x)) где: SQUARE(++x) расширяется до: ((++x)*(++x)) инкрементируя x дважды. Вы не можете решить эту проблемгу в Си, а в Си++ можете. Простая встроенная функция работает вполне удовлетворительно, в таком виде: inline int square( int x ){ return x * x; } не давая побочного эффекта. Тем не менее, она допускает лишь целочисленные аргументы. Шаблон функции, который расширяется во множество перегруженных встроенных функций, является более общим решением: template <class type> inline type square( type x ){ return x * x; } К несчастью, это срабатывает только в простых ситуациях. Следующий шаблон не может обработать вызов max(10, 10L), потому что не совпадают типы аргументов: template <class type> inline type max( type x, type y ){ return (x > y) ? x : y; } Для обработки max(10, 10L) вы должны использовать прототип, чтобы принудить к расширению по тому варианту max() , который может выполнить данную работу:
|
© 2006 - 2024 pmbk.ru. Генерация страницы: 0
При копировании материалов приветствуются ссылки. |