Хотя стандарт C ++ не имеет такого требования, некоторым компиляторам требуется, чтобы все шаблоны функций и классов были доступны в каждой используемой системе переводов. Фактически для этих компиляторов тела шаблонных функций должны быть доступны в файле заголовка. Повторить: это означает, что эти компиляторы не позволят их определять в файлах без заголовка, таких как .cpp-файлы
Существует ключевое слово export , которое должно смягчать этот проблема, но он нигде не близок к тому, чтобы быть портативным.
Я обычно использую то, что иногда называют, 'правая рука по часовой стрелке управляют'. Это идет как это:
существует дополнительное метаправило, которое должно заботиться о:
Здесь, 'идя' и 'перемещаясь' куда-нибудь означает читать символ там. Правила для этого:
*
- указатель на [1 117] ()
- функция, возвращаясь (int, int)
- функция, берущая два ints и возвращающаяся int
, char
, и т.д. - int
, char
, и т.д. []
- массив [1 121] [10]
- массив десять Так, например, int* (*xyz[10])(int*, char)
читается как:
xyz
массив десять
указатель на [1 130]
функция, берущая интервал* и символ и возвращающаяся
интервал*
Автоматическое решение является cdecl.
В целом, Вы объявляете переменную путем, Вы используете ее. Например, Вы разыменовываете указатель p как в:
char c = * p
Вы объявляете его подобно выглядящим способом:
char * p;
То же идет для волосатых указателей функции. Давайте объявим, что f старый добрый "указатель на указатель возврата функции на интервал" и внешнее объявление только, чтобы быть забавным. Это - указатель на функцию, таким образом, мы запускаем с:
extern * f();
Это возвращает указатель на интервал, так где-нибудь впереди там существует
extern int * * f(); // XXX not quite yet
Теперь, который является корректной ассоциативностью? Я никогда не могу помнить, так используйте некоторую круглую скобку.
extern (int *)(* f)();
Объявляют его способ, которым Вы используете его.
cdecl предлагает интерфейс командной строки так, давайте дадим ему попытку:
cdecl> explain int ***c[][]
declare c as array of array of pointer to pointer to pointer to int
другой пример
explain int (*IMP)(ID,SEL)
declare IMP as pointer to function (ID, SEL) returning int
Однако существует целая глава об этом в книге "C Непостижимые тайны", названный "Восстанавливание объявлений в C.
Cdecl (и C++ decl) является программой для кодирования и декодирования C (или C++) описания типа.
http://gd.tuwien.ac.at/linuxcommand.org/man_pages/cdecl1.html
Назад, когда я делал C, я использовал программу, названную "cdecl". Кажется, что это находится в Ubuntu Linux в cutils или cdecl пакете, и это, вероятно, доступно в другом месте.
Общие проблемы удобочитаемости включают указатели функции и то, что массивы являются действительно указателями , и что многомерные массивы являются действительно единственными массивами размера (которые являются действительно указателями). Hope, которая помогает некоторым.
В любом случае, каждый раз, когда Вы действительно понимаете объявления, возможно, можно выяснить способ упростить их для создания их более читаемыми для следующего парня.
Одно слово: cdecl
Damnit, разбитый на 15 секунд!
Эта статья объясняет относительно простые 7 правила, которые позволят Вам считать любое объявление C, если Вы будете желать или должными быть сделать так вручную: http://www.ericgiguere.com/articles/reading-c-declarations.html
- Находит идентификатор. Это - Ваша начальная точка. На листке бумаги запишите, "объявляют идентификатор как".
- Взгляд направо. Если нет ничего там, или существует правая круглая скобка")", goto шаг 4.
Вы теперь расположены или на массив (левая скобка) или на функцию (левая круглая скобка) дескриптор. Может быть последовательность их, закончившись или с несопоставленной правой круглой скобкой или с концом оператора объявления (точка с запятой или "=" для инициализации). Для каждого такого дескриптора, читая слева направо:
- , если пустой массив" []", запишите "массив"
- , если массив с размером, запишите "размер массива"
- , если функция" ()", запишите "функцию, возвратившись"
Остановка в несопоставленной круглой скобке или конце оператора объявления, какой бы ни на первом месте.
- Возврат к стартовой позиции и взгляду налево. Если нет ничего там, или существует левая круглая скобка" (", goto шаг 6.
- Вы теперь расположены на дескриптор указателя, "* ". Может быть последовательность их налево, закончившись или с несопоставленной левой круглой скобкой" (" или запуск оператора объявления. Чтение справа налево, для каждого дескриптора указателя пишет "указатель на". Остановитесь в несопоставленной круглой скобке или запуске оператора объявления, какой бы ни является первым.
- В этой точке у Вас есть или заключенное в скобки выражение или полный оператор объявления. Если Вы имеете заключенное в скобки выражение, рассматриваете его как Вашу новую начальную точку и возвращаетесь к шагу 2.
- , Записывают спецификатор типа. Остановиться.
, Если Вы соглашаетесь с инструментом, тогда я вторые предложение для использования программы cdecl
: http://gd.tuwien.ac.at/linuxcommand.org/man_pages/cdecl1.html
Только что наткнулся на поясняющий раздел в « Развитие языка C »:
Для каждого объекта такого составного типа уже существовал способ упомяните базовый объект: проиндексируйте массив, вызовите функцию, используйте оператор косвенного обращения к указателю. Аналогичные рассуждения привели к синтаксису объявления для имен, отражающему синтаксис выражения, в котором обычно встречаются имена. Таким образом,
int i, * pi, ** ppi;
объявляют целое число, указатель на целое число, указатель на указатель на целое число. Синтаксис этих объявлений отражает наблюдение, что все i, * pi и ** ppi дают тип int при использовании в выражении. Точно так же
int f (), * f (), (* f) ();
объявляют функцию, возвращающую целое число, функцию, возвращающую указатель на целое число, указатель на функцию, возвращающую целое число;
int * api [10], (* pai) [10];
объявляют массив указателей на целые числа и указатель на массив целых чисел. Во всех этих случаях объявление переменной похоже на ее использование в выражении, тип которого указан в заголовке объявления.