Правила программирования на Си и Си++

       

Операция — это сокращение (без сюрпризов)


Операция — это не произвольный значок, означающий все, что вы ни пожелаете. Это аббревиатура англоязычного слова. Например, символ +

значит "прибавить", поэтому вы не должны заставлять перегруженный operator+()

делать что-нибудь еще. Хотя здесь все ясно (вы можете определить a + b для вычитания b из a, но не должны делать этого), я на самом деле веду речь о проблемах более творческого характера.

Вы можете благоразумно доказывать, что, когда выполняете конкатенацию, то "прибавляете" одну строку к концу другой, поэтому перегрузка + для конкатенации может быть приемлема. Вы также можете доказывать, что разумно использовать операции сравнения для лексикографического упорядочивания в классе string, поэтому перегрузка операций , == и т.д. также вероятно пойдет. Вы не сможете аргументировано доказать, что – или * имеют какой-нибудь смысл по отношению к строкам.

Другим хорошим примером того, как нельзя действовать, является интерфейс Си++ iostream. Использование сдвига () для обозначения "вывод" является нелепым. Ваши функции вывода в Си назывались printf(), а не shiftf(). Я понимаю, что Страуструп выбрал сдвиг, потому что он сходен с механизмом перенаправления ввода/вывода различных оболочек UNIX, но этот довод на самом деле не выдерживает проверки. Страуструп исходил из того, что все программисты на Си++ понимают перенаправление в стиле UNIX, но эта концепция отсутствует в некоторых операционных системах — например, в Microsoft Windows. К тому же, для того, чтобы аналогия была полной, операция

должна быть перегружена для выполнения операции затирания, а

добавления в конец. Тем не менее, тот факт, что и

имеют различный приоритет, делает реализацию такого поведения затруднительной. Дело осложняется тем, что операторы сдвига имеют неправильный уровень приоритета. Оператор типа cout

x += 1 не будет работать так, как вы ожидаете, потому что у

более высокий приоритет, чем у +=, поэтому оператор интерпретируется как (cout x) += 1, что неверно. Си++ нуждается в расширяемости, обеспечиваемой системой iostream, но он вынужден добиваться ее за счет введения операторов "ввода" и "вывода", имеющих низший приоритет по отношению к любому оператору языка.


Аналогия проблеме " сдвиг как вывод" может быть найдена в проектировании компьютерных систем. Большинство проектировщиков аппаратуры были бы счастливы использовать +
вместо OR, а *
вместо AND, потому что такая запись используется во многих системах проектирования электронных компонентов. Несмотря на это, перегрузка операции operator+() в качестве OR
явно не нужна в Си++. К тому же, лексема означает "сдвиг" в Си и Си++; она не означает "вывод".
Как завершающий пример этой проблемы — я иногда видел реализации класса "множество", определяющие | и со значениями "объединение" и "пересечение". Это может иметь смысл для математика, знакомого с таким стилем записи, но при этом не является выражением ни Си, ни Си++, поэтому будет незнакомо для вашего среднего программиста на Си++ (и вследствие этого с трудом сопровождаться). Амперсанд является сокращением для AND; вы не должны назначать ему произвольное значение. Нет абсолютно ничего плохого в a.Union(b) или a.intersect(b). (Вы не можете использовать a.union(b) со строчной буквой u,
потому что union
является ключевым словом).

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