Информационный сайт

 

Реклама
bulletinsite.net -> Книги на сайте -> Программисту -> Мизрохи С.В. -> "Turbo Pascal и объектно-ориентированное программирование" -> 12

Turbo Pascal и объектно-ориентированное программирование - Мизрохи С.В.

Мизрохи С.В. Turbo Pascal и объектно-ориентированное программирование — М.: Финансы и статистика , 1992. — 192 c.
ISBN 5-279-00903-2
Скачать (прямая ссылка): efektispolzc2000.djvu
Предыдущая << 1 .. 6 7 8 9 10 11 < 12 > 13 14 15 16 17 18 .. 105 >> Следующая

Впрочем, терять сон из-за подобных пустяков не стоит. Если об определении забудете вы, то напомнит компоновщик.
Старые компиляторы могут не поддерживать принятый здесь синтаксис, так как в более ранних версиях языка было запрещено задавать значения статических Членов класса во время их объявления. Более того, инициализация в классе допускалась только для целых типов (таких как int, bool, char и пр.) и для констант. Если вышеприведенный синтаксис не работает, то начальное значение следует задавать в определении:
Переход от С к С++
!11Ii
class EngineeringConstants { // Это находится в файле заголовка класса, private:
static const double FUDGE_FACTOR;
};
Il Это находится в файле реализации класса, const double EngineeringConstants::FUDGE_FACTOR = 1.35;
Единственное исключение обнаруживается тогда, когда для компиляции класса необходима константа. Например, при объявлении массива GamePlayer: : scores в листинге, приведенном выше, в момент компиляции может потребоваться задание его размера. Для того чтобы работать с компилятором, ошибочно запрещающим инициализировать целые константы внутри класса, следует применять технику, которая шутливо называется «трюком с перечислением». Она основана на том, что переменные перечисляемого типа можно использовать там, где ожидаются целые числа, поэтому GamePlayer определяют следующим образом: ,
class GamePlayer { private:
enum { NUMJTURN S = 5 }; Il "Трюк с перечислением" - делает
11 из NUM_TURNS символ со значением 5. int scores[NUM_TURNS]; Il Нормально.
};
Если вы имеете дело не с примитивным компилятором, написанным до 1995 года и представляющим собой только исторический интерес, то считайте, что вам повезло: необходимость использовать этот трюк отпадет сама собой. Тем не менее его нужно знать, поскольку для многих из нас устаревший компилятор - «тяжелое наследство», доставшееся от прошлых, не столь изысканных времен.
Вернемся к препроцессору. Другой частый случай неправильного использования директивы #def ine - создание макросов, которые выглядят как функции, но не обременены накладными расходами функционального вызова. Канонический пример - вычисление максимума двух значений:
ttdefine max(a,b) ((а) > (b) ? (a) : (b))
В этой небольшой строчке содержится так много недостатков, что даже не совсем понятно, с какого проще начать.
Всякий раз, когда вы пишете макрос подобный этому, необходимо помнить, что все аргументы следует заключать в скобки. В противном случае у Пользователей будут возникать серьезные проблемы с применением таких макросов в выражениях. Но, даже если вы все сделаете верно, посмотрите, какие странные вещи могут при этом произойти:
int а = 5, b = 0; «•
max (++a, b) ; // а увеличивается дважды.
тах(++а, Ь+10); // а увеличивается один раз.
Происходящее внутри max зависит от того, что с чем сравнивается]
Правило 2 III
К счастью, вам нет нужды мириться с поведением, так сильно противоречащим привычной логике. Существует метод, позволяющий добиться такой же эффективности, как при использовании макросов. В таком случае обеспечиваются как предсказуемость поведения, так и контроль типов аргументов (что характерно для обычных функций). Этот результат достигается применением встраиваемых функций (см. правило 33):
inline int max (int a, int b) { return a > b ? a : b; }
Новая версия max несколько отличается от предыдущей, поскольку она может работать только с целыми аргументами. Возникшую проблему удачно решает шаблон:
template<class Т>
inline const Т& max (const Т& a, const Т& b) { return а > b ? a : b; }
Он генерирует целое семейство функций, каждая из которых берет два приводимых к одному типу объекта и возвращает ссылку (с модификатором const) на больший из двух объектов. Поскольку вам неизвестно, каким будет тип Т, для эффективности передача и возврат значения происходят по ссылке (см. правило 22).
Кстати говоря, прежде чем вы решите писать шаблон для какой-либо функции, подобной max, узнайте, не присутствует ли она уже в стандартной библиотеке (см. правило 49). В случае с max вы можете воспользоваться плодами чужих усилий: max является частью стандартной библиотеки С++.
Возможность использования const и inline уменьшает необходимость в препроцессоре, но не устраняет ее полностью. Еще далек тот день, когда вы сможете обходиться без #include, между тем как #ifdef /ttifndef продолжают играть важную роль в контроле над компиляцией. Пока'рано списывать со счетов препроцессор, но, без сомнения, уже сейчас стоит задуматься над тем, как освободиться от него в дальнейшем.
Правило 2. Предпочитайте <iostream> использованию <stdio.h>
Да, они переносимы. Да, они эффективны. Да, вы уже знаете, как их использовать. Но какой бы благоговейный восторг они ни вызывали, факт остается фактом: операторы scanf и print f и им подобные далеки от совершенства. В частности, °ни не осуществляют контроль типа и к тому же нерасширяемы. Поскольку контроль типов и расширяемость - краеугольные камни идеологии С++, то лучше всего с самого начала во всем опираться на них. Кроме того, семейство функций Printf /scanf отделяет переменные, которые необходимо прочитать или записать, от форматирующей информации, управляющей записью и чтением, в точности так же, как это делает FORTRAN. Настало время распрощаться с пятидесятыми.
Предыдущая << 1 .. 6 7 8 9 10 11 < 12 > 13 14 15 16 17 18 .. 105 >> Следующая
Реклама
Авторские права © 2009 AdsNet. Все права защищены.
Rambler's Top100