2009-10-29 7 views
5

ОТКАЗ: Я не сделал C++ в течение некоторого времени ...C/C++ функция/метод декорирования

ли распространены в настоящее время, чтобы украсить C/C++ функции/объявления методов для того, чтобы улучшить читаемость?

Сырой Пример:

void some_function(IN int param1, OUT char **param2);

с макросами В и OUT, определенные с пустым тела (то есть легкая документация, если вы будете в этом примере). Конечно, я понимаю, что это происходит несколько параллельно с «блоком комментариев док», связанным с методом/функцией.

Не могли бы вы привести некоторые другие примеры ... если эта тема полезна для сообщества. Пожалуйста, помните, что приведенный выше пример является тем, чем он является.

+8

Я думаю, что лучше пометить * INs ключевым словом 'const'. –

+6

Yuck! Сделать будущих сопровождающих искать бесполезный макрос вместо того, чтобы просто помещать эту информацию в комментарий? Риск вмешательства в другие существующие макросы? Нет, спасибо! – ctd

+0

@Nick D, иногда вы хотите использовать не-const pass by value для параметров IN как небольшую оптимизацию 'type f (значение типа) {value.op(); возвращаемое значение; } 'Это позволяет компилятору не только копировать возвращаемое значение, но и создавать входные копии, если переданный аргумент является временным. –

ответ

17

Я не стал бы признателен за такое оформление.

Гораздо лучше использовать сопзЬ и ссылки и постоянные ссылки, как в

void some_function(AClass const &param1, AnotherClass &param2) 

Обычно INT передаются по значению, а не по ссылке, поэтому я использовал AClass и AnotherClass для примера. Мне кажется, что добавление empy IN и OUT будет отвлекать.

0

Я этого раньше не видел. Я бы подумал, что было бы лучше разместить такую ​​информацию в комментариях.

1

Я пытаюсь использовать:

  • значения для входных параметров или ссылки, если они большие
  • Ссылки для выходных параметров
  • Указатели, чтобы дать право собственности на вызываемой функции

Наиболее времени действительно легко увидеть, какие параметры IN или OUT, конечно, правильные имена в декларации являются хорошей документацией.

Я нахожу эти IN, OUT дополнения раздражающими.

2

Не в C++, я не сделал программирование C профессионально, но по крайней мере в C++ типа параметров сам за себя:

void f(std::string const &); // input parameter 
void f(std::string);   // input parameter again (by value) 
void f(std::string&);  // in/out parameter 
std::string f();    // output 

Это вместе с в-коду документирования инструментов (Doxygen) где вы добавьте некоторый контекст к параметрам (какие значения ожидаются или неприемлемы для функции, как функция меняет переданные объекты ...

О указателях: мы склонны ограничивать исходные указатели в наших интерфейсах методов. , они могут быть использованы, но в целом предпочтительны интеллектуальные указатели. Затем снова семантика собственности исходит из выбора e умного указателя: shared_ptr <> для разводной совместной ответственности (или при необходимости), auto_ptr <>/unique_ptr <> для единоличного владения (обычно как возвращаемое значение от фабрик, местных жителей или атрибутов участника) ...

+0

'T &' могут быть как «out», так и «in/out». –

+0

Да, но это должен быть полностью построенный объект, поэтому он не «чисто». Я склонен их видеть (это только я, а не общий язык) как параметры ввода/вывода, независимо от того, обрабатываются ли они/читаются внутри. Хотя это приемлемо, мне потребуется объяснение аргумента, полученного по ссылке, значение которого не используется внутри функции в обзоре кода. Места, где это приемлемо: функция, возвращающая необработанный буфер (указатель на блок памяти), который также обновляет размер, переданный как параметр (только * после того, как * они действительно * оправданны без использования более безопасной конструкции) или как оптимизация, если это необходимо –

1

Я видел это, но я не думаю, что я бы сказал, что это «обычный».

Интерфейс Win32 API (не C C++) использует что-то подобное:

WINADVAPI 
BOOL 
WINAPI 
CreateProcessWithLogonW(
    __in  LPCWSTR lpUsername, 
    __in_opt LPCWSTR lpDomain, 
    __in  LPCWSTR lpPassword, 
    __in  DWORD dwLogonFlags, 
    __in_opt LPCWSTR lpApplicationName, 
    __inout_opt LPWSTR lpCommandLine, 
    __in  DWORD dwCreationFlags, 
    __in_opt LPVOID lpEnvironment, 
    __in_opt LPCWSTR lpCurrentDirectory, 
    __in  LPSTARTUPINFOW lpStartupInfo, 
    __out  LPPROCESS_INFORMATION lpProcessInformation 
    ); 

В случае Visual C++ 2005 и более поздних версий компиляторов, они на самом деле карта декларациям как __$allowed_on_parameter и проверяются во время компиляции.

7

Windows заголовки фактически делают именно это. См. Header Annotations для получения полного списка использованных аннотаций. Например»

DWORD 
WINAPI 
GetModuleFileName(
    __in_opt HMODULE hModule, 
    __out_ecount_part(nSize, return + 1) LPTSTR lpFilename, 
    __in DWORD nSize 
    ); 

Для этой функции, hModule является необязательным входным параметром, lpFilename является выходным параметром, который хранит максимум nSize элементов и символов, которые будут содержать (возвращаемое значение функции) +1 элементов символов в нем по возвращении и nSize является входным параметром.

+1

+1. Эта запись в блоге имеет фон и несколько примеров: http://blogs.msdn.com/michael_howard/archive/2006/05/19/602077.aspx –

+6

Но это не пустые макросы - в конце концов они расширяются до атрибутов SAL таких как '[SA_Pre (...)]' и '[SA_Post (...)]', которые фактически обрабатываются компилятором. –

5

Для целей документации достаточно хорошо написанный блок комментариев, поэтому они не предназначены для каких-либо целей. Кроме того, некоторые синтаксисы комментариев к документации имеют специальный синтаксис только для такого вещь, например, учитывая Doxygen, вы можете написать:

/** 
* @param[in] param1 ... 
* @param[out] param2 ... 
**/ 
void some_function(int param1, char **param2); 
+0

... но как насчет вещей вне документации? – jldupont

+1

Что вы имеете в виду? Вы можете и должны документировать все методы, а не только публичные API. Для создания документации обычно существует способ обозначить, какие методы «для частного использования», так что они не попадают в общедоступные документы - например, '\ internal' в Doxygen. –

+0

Если вы не смотрите на документы, вы смотрите на исходный код. Если это не является по крайней мере достаточно очевидным, вам нужно реорганизовать и/или переименовать элементы в источнике вместо украшения. –

4

Я думаю, что это плохая идея. Тем более, что любой может прийти и определить макросы IN/OUT и оставить вас в куче больших неприятностей.

Если вы действительно хотите задокументировать его, добавьте комментарии.

void some_function(/* IN */ int param1, /* OUT */ char **param2); 

Также зачем использовать выход, когда возвращаемое значение будет работать нормально.
Также я бы предпочел использовать pass ref и const ref для указания моих намерений. Также компилятор теперь делает относительно хороший оптимизм для намерения, когда ваш код является правильным.

void some_function(/* IN */ int const& param1, /* OUT */ char*& param2); 
// OK for int const& is kind of silly but other types may be usefull. 
+0

хорошая точка ... спасибо! – jldupont

+0

@Martin: что касается сделанного вами комментария «char *», у меня было мое заявление об отказе в верхней части вопроса ;-) – jldupont

+1

/* +1 */(в отличие от PLUSONE) –

1

Единственное хуже, чем это было замечено давно в программе C, написанной Pascal Dev:


#define begin { 
#define end } 

int main(int argc, char* argv[]) 
begin 
    ... 
end 
0

Я видел использование префиксов i_, o_, io_ в дополнение к информации по типам параметров :

void some_function(int i_param1, char** o_param2, int& io_param3);