Делайте объявления функций на основе определений функций

Я написал файл .cpp с рядом функций, и теперь мне нужно объявить их в заголовочном файле. Мне пришло в голову, что я мог бы найти файл для имени класса и получить объявления таким образом, и это тоже сработало бы достаточно хорошо, если бы перед определением было полное объявление функции - код возврата, имя и параметры. (но не тело функции) -- было на одной строке.

Мне кажется, что это то, что было бы вообще полезно, и должно быть решено несколько раз. Я с удовольствием редактирую вывод и не беспокоюсь о крайних случаях; все, что дает мне правильные результаты в 95% случаев, было бы здорово.

Итак, если, например, в моем файле .cpp было:

i2cstatus_t NXTI2CDevice::writeRegisters(
    uint8_t  start_register,    // start of the register range
    uint8_t  bytes_to_write,    // number of bytes to write
    uint8_t* buffer = 0)        // optional user-supplied buffer
{
...
}

и ряд других подобных функций, возвращающих это:

i2cstatus_t NXTI2CDevice::writeRegisters(
        uint8_t  start_register,    // start of the register range
        uint8_t  bytes_to_write,    // number of bytes to write
        uint8_t* buffer = 0)

для включения в заголовочный файл, после небольшой доработки, было бы нормально.

Получение этого обратно:

i2cstatus_t writeRegisters(
        uint8_t  start_register,    
        uint8_t  bytes_to_write,    
        uint8_t* buffer);

или это:

i2cstatus_t writeRegisters(uint8_t  start_register, uint8_t  bytes_to_write, uint8_t* buffer);

было бы еще лучше.


person Clinton Blackmore    schedule 05.06.2010    source источник
comment
Я думаю, вы пытаетесь усложнить то, что почти всегда удается скопировать и вставить. Я думаю, что использовать ваш инструмент было бы сложнее, если бы у вас не было встроенной поддержки редактора, и он мог бы редактировать файлы, а не просто создавать их.   -  person Stephen    schedule 05.06.2010
comment
@Emile Вопрос в том, учитывая файл .cpp с рядом функций-членов класса, как мне извлечь функции, чтобы поместить определения в файл заголовка?   -  person Clinton Blackmore    schedule 05.06.2010
comment
@Stephen - копировать и вставлять, потому что утомительно (а иногда и подвержено ошибкам), когда есть много функций.   -  person Clinton Blackmore    schedule 05.06.2010


Ответы (2)


Я думаю, вы поняли это задом наперёд. Декларация является важной частью здесь. Реализация — это детали. Вы пытаетесь избавить себя от набора текста за счет недостаточно тщательного проектирования и создания интерфейса, что очень важно для любого языка, но в C++ это важно.

Начните с заголовочных файлов. Затем, если хотите, сгенерируйте тела реализации заглушек и, возможно, оболочки тестовых случаев, а затем начните заполнять функции. Строить, тестировать, исправлять, расширять, кожать, повторять.

Редактировать:

Разглагольствование, не вписывающееся в комментарий:

Тогда мой вопрос: если это не «публичный интерфейс», зачем он вам в заголовке? Мое твердое мнение состоит в том, что все, что содержится в заголовочном файле, является интерфейсом, независимо от того, насколько он мал и какая внутренняя/внешняя подсистема предоставляет его какой-либо другой части. Это не кажется значительным для проекта одного парня. Но рано или поздно второй паре глаз (возможно, даже вашим собственным, через три-шесть месяцев) придется еще раз пройтись по этому интерфейсу и разобраться, почему он был обнародован, о чем думал автор, какова цель. , и т.д. и т.п.

Тривиально? Да! Но я не могу сказать вам, сколько раз я проклинал оригинального автора (включая себя) некоторого кода, который мне приходилось читать и понимать (снова), и это тривиальное эмпирическое правило спасло бы мне столько волос :)

Редактировать 2:

... how do I declare a private member function without declare it with the rest of the class, in the header?

Это известная ошибка самого C++. См., например, статью Саттера (Mostly) Private. Есть несколько способов справиться с этим на уровне дизайна:

  • В C++ не все должно быть классом, бесплатные функции великолепны. Объявите и используйте указатель функции, реализуйте набор соответствующих функций в файле .cpp, поместите указатели в таблицу или контейнер STL.
  • Вперед объявите класс, чтобы он был непрозрачным для пользователя, измените интерфейс, чтобы он работал со ссылкой или указателем.
  • Используйте идиому pimpl (также здесь)
person Nikolai Fetissov    schedule 05.06.2010
comment
В целом, я согласен с вашим мнением. Но... 1) на самом деле не имеет значения, что вы пишете первым, пока ваш интерфейс разработан первым и 2) C++ имеет досадное свойство помещать детали реализации в заголовочные файлы. Обычно я не пишу свои приватные объявления до их реализации. В любом случае, этот ответ не помогает ОП достичь любого подхода :) - person Stephen; 05.06.2010
comment
Это не так. Делать тоже было нечего. Сосредоточьтесь на общедоступном интерфейсе. - person Nikolai Fetissov; 05.06.2010
comment
Бывают случаи, когда очевидно, что вам нужна данная функция — и не обязательно для общедоступного интерфейса. Например, если вы пишете эмулятор ЦП с функцией для каждого кода операции, то у вас есть большое количество простых функций, которые на самом деле не нуждаются в предварительном проектировании. В таком случае, почему бы не закодировать их, а затем извлечь имена функций для заголовка? - person Clinton Blackmore; 05.06.2010
comment
Затем вы используете полиморфизм, потому что написание функции для каждого возможного кода операции было бы самоубийством для расширяемости. - person Puppy; 05.06.2010
comment
В яблочко. Или напишите скрипт для создания таблицы указателей на эти простые функции в файле реализации. - person Nikolai Fetissov; 05.06.2010
comment
Что касается, если это не общедоступный интерфейс, зачем он вам нужен в заголовке, как мне объявить частную функцию-член без объявления ее с остальной частью класса в заголовке? - person Clinton Blackmore; 05.06.2010
comment
@DeadMG Пять лет назад я написал эмулятор 80186. Я полагаю, каждая операция имела свою функцию, а не каждый код операции. (Другая часть кода брала код операции, вычисляла операцию и определяла, какие регистры/адреса памяти задействованы, а затем вызывала функцию.) Все различные операции в какой-то момент все равно должны быть написаны. - person Clinton Blackmore; 05.06.2010
comment
Спасибо за примечания в Edit 2. Это очень интересно. - person Clinton Blackmore; 06.06.2010

Я скомпилировал яркие ctags версии 5.8. Эта команда дает мне то, что я хочу:

/usr/local/bin/ctags -x --c-kinds=f $SOURCE |
awk -v OFS=" " '$1=$1' |
cut -d " " -f 5- |
sed -e 's/[A-Za-z]*:://g' |
sed -e 's/)$/);/'

где вы подставляете имя интересующего вас файла вместо $SOURCE.

Обратите внимание, что команда ctags сама по себе дает разумный вывод, и вы можете добавить флаг -u, если хотите, чтобы вывод был в том порядке, в котором он появляется в файле, а не в алфавитном порядке.

person Clinton Blackmore    schedule 05.06.2010
comment
Ваша последняя строка 'sed' может столкнуться с проблемами, если функция содержит указатель на функцию, среди прочего возможного использования круглых скобок в одной функции. Рассмотрим: void (*signal(int sig, void (*func)(int)))(int);. - person Jonathan Leffler; 06.06.2010
comment
Я думаю, если вы обнаружите, что вам нужно использовать это часто, вы, вероятно, делаете это неправильно ... но +1 за выяснение решения и его публикацию :) (И в настоящее время ответ с наибольшим количеством голосов не помогает на все) - person Stephen; 06.06.2010
comment
@Jonathan Leffler - Спасибо за правку, стало намного понятнее. На самом деле я считал, что при глобальной замене вставка точки с запятой может вызвать проблему. Хотя я полагал, что в большинстве случаев это сработает. - person Clinton Blackmore; 06.06.2010
comment
@Stephen - Спасибо, что вернулся и за добрые слова. Я согласен с вами - обычно сначала нужно разработать общедоступный интерфейс. - person Clinton Blackmore; 06.06.2010
comment
При каких обстоятельствах sed -e 's/)$/);/' даст неверный результат? Также, конечно, два вызова sed можно комбинировать, но в данном приложении это не имеет большого значения. - person Jonathan Leffler; 06.06.2010
comment
@ Джонатан - Хороший звонок. Я не вижу никаких обстоятельств, при которых это могло бы потерпеть неудачу. Я обновлю пост. - person Clinton Blackmore; 06.06.2010
comment
Обратите внимание, что функции, которые принимают много параметров (и не помещаются в пределах одной ширины экрана), показывают только открывающую скобку и не содержат параметров. : ( - person Clinton Blackmore; 23.06.2010