Программирование >>  Полиморфизм без виртуальных функций в с++ 

1 ... 11 12 13 [ 14 ] 15 16 17 ... 144


Проблемы синтаксиса

Разрешение опускать спецификатор типа (по умолчанию считается, что это int) также приводит к сложностям. Например:

/* стиль с (предлагалось запретить): */ static а; /* неявно: тип а равен int */ f(); /* неявно: возвращает int */

предлагалось в С with Classes:

static int a; int f();

Негативная реакция пользователей на изменения в этой области была очень сильна. Они настолько ценили краткость С, что отказывались пользоваться языком, который требовал явно писать спецификаторы типов. Я отказался от из.мене-ния. Не ду.маю, что здесь вообще был выбор. Разрешение неявного int - источник многих проблем в грамматике C-i-i-. Замечу, что давление шло со стороны пользователей, а не административных органов или кабинетных экспертов по языкам. Наконец, спустя десять лет, комитет ANSI/ISO по стандартизации C+-I- (см. главу 6) решился запретить неявный int. А значит, еще через десяток лет мы, возможно, от него и избавимся. Но с помощью инструментальных средств или предупреждений компилятора отдельные пользователи уже сейчас могут начать защищаться от вызванных неявны.м int недоразумений, например, таких:

void f (const Т) ; константный аргумент типа Т или

аргумент с именем Т типа const int? (на самом деле первое)

Однако синтаксис определения функции с указанием типов аргументов внутри скобок использовался в С with Classes и C+-i- и позднее был одобрен комитетом ANSI С:

[а,Ь) char Ь; /* определение функции в стиле K&R */ /* ... */

int f(int а, char b) определение функции в стиле С++ ...

Я рассматривал и возможность введения линейной нотации для объявлений. В С применяется прием, когда объявление имени имитирует его использование, а в результате получаются объявления, которые трудно читать и записывать, и шансы, что человек или программа спутают объявление и выражение, растут. Неоднократно отмечалось: проблема с синтаксисом объявлений в С заключается в том, что оператор объявления * ( указатель на ) - префиксный, а операторы объявления [ ] ( массив ) и () ( возвращающая функция ) - постфиксные. Это заставляет использовать скобки для устранения двусмысленности:

/* стиль с */

int* v[10]; /* массив указателей на int */

int (*р)[10]; /* указатель на массив int */



Вместе с Дугом Макилроем, Эндрю Кенигом, Джонатаном Шопиро и другими я решил ввести постфиксный оператор указатель на -> как альтернативу префиксному *:

радикальное изменение: V: [10]->int ; массив указателей на int р: ->[10]int; указатель на массив int

менее радикальное изменение: int v[10]->; массив указателей на int int р->[10]; указатель на массив int

Менее радикальный вариант имел то преимущество, что постфиксный оператор объявления -> мог сосуществовать с префиксным оператором * в течение переходного периода. А по его завершении оператор объявления * и лишние скобки можно было бы просто убрать из языка. Польза от этой схемы заметна: скобки потребовались бы только для записи объявления функции, поэтому возможность путаницы и грамматические тонкости просто исчезли бы (см. также [Sethi, 1981 ]). Если бы все операторы объявления были постфиксными, то объявления могли бы читаться слева направо. Например,

int f(char)->[10]->(double)->;

означало бы функцию f, возвращающую указатель на массив указателей на функции, возвращающие указатель на int. Попробуйте написать это на стандартном C/C++! К сожалению, я не довел данную идею до конца и так и не сделал полную реализацию. Пользователи вынуждены строить определения сложных типов с помощью typedef:

typedef int* Dtol(double); функция, принимающая double

и возвращающая указатель на Int typedef Dtol* V10[10]; массив из 10 указателей на Dtol VIО * f(char); lit принимает char и возвращает указатель

на V10

В конце концов, я решил оставить все как есть, обосновав это тем, что любое изменение синтаксиса лишь увеличит (по крайней мере, временно) путаницу. И хотя старый синтаксис - сущий подарок для любителей придираться по пустякам и желающих высмеивать С, для программистов на С он большой проблемы не составляет. Все же я не уверен, что поступил правильно. Ведь от нелогичного синтаксиса С страдаю и я, и другие разработчики компиляторов С++, составители документации, разработчики инструментальных средств. Пользователи, конечно, могут изолировать себя от таких проблем, довольствуясь только малым, простым для понимания подмножеством синтаксиса объявлений C/C++ (см. раздел 7.2), собственно, так они и поступают.

2.S.2. Тэги структур и имена типов

Для удобства пользователей в С++ было введено одно синтаксическое упрощение, потребовавшее, правда, дополнительной работы для разработчиков компиляторов и вызвавшее некоторые проблемы совместимости с С. В С имени



Проблемы синтаксиса

структуры, так называемому тэгу, всегда должно предшествовать ключевое слово struct. Например:

struct buffer а; /* в С struct необходимо */

В С with Classes меня это не устраивало, поскольку получалось, что синтаксически определенные пользователем типы можно было отнести ко второму сорту . Но, потерпев неудачу с другими попытками изменения синтаксиса, я не хотел нарываться на неприятности еще раз и внес это изменение (когда С with Classes превратился в C-i-i-) только по настоятельно.му требованию Тома Каргилла Имя структуры, объединения и кЛасса в C-i-i- - просто имя типа и не требует специального обозначения:

buffer а; С++

Битвы на поле совместимости с С продолжались несколько лет (см. также раздел 3.12). Например, следующая запись допустима в С:

struct S { int а; }; int S;

void f(struct S x) {

x.a=S; S- переменная типа int

Она также допустима и в С with Classes, и в C-i-i-, но в течение многих лет мы искали формулировку, которая в целях совместимости допускала бы такой немного странный, но безвредный код в C-i-i-. Ведь, если бы это было разрешено, следовало запретить следующее:

void g(S X) ошибка: S - переменная типа int

х.а = S;

Насущная необходимость решить данную проблему следовала из того, что в некоторых заголовочных файлах для системы UNIX, прежде всего в stat .h встречались и структура, и переменная или функция с одним и тем же именем. Такие вопросы совместимости немаловажны, а для языковых пуристов это особо лакомый кусочек. К сожалению, пока не найдено удовлетворительное (и как правило, тривиальное) решение и данным вопросам приходится уделять слишком много внимания и сил. А когда решение найдено, проблема совместимости становится просто скучной, поскольку в ней нет никакой интеллектуальной ценности, а есть лишь голый практицизм. Принятое в C-i-i- решение проблемы множественных пространств имен в С состоит в том, что одним именем может обозначаться как класс, так и переменная или функция. Таким образом, имя относится не к классу, если только оно явно не уточнено одним из ключевых слов struct, class или union.

Споры с упрямыми старыми пользователями С, так называемыми экспертами, а также реальные проблемы совместимости с С были и остаются одним из самых трудных и вызывающих разочарование аспектов разработки C-i-i-.



1 ... 11 12 13 [ 14 ] 15 16 17 ... 144

© 2006 - 2024 pmbk.ru. Генерация страницы: 0
При копировании материалов приветствуются ссылки.
Яндекс.Метрика