|
Программирование >> Полиморфизм без виртуальных функций в с++
Проблемы синтаксиса Разрешение опускать спецификатор типа (по умолчанию считается, что это 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-.
|
© 2006 - 2024 pmbk.ru. Генерация страницы: 0
При копировании материалов приветствуются ссылки. |