Каковы типичные соглашения об именах для публичных и частных функций OO C? [закрыто]

12

Короткий вопрос
Есть ли типичный способ назвать «публичных» и «частных» участников проекта OO C?

Предпосылки
Я полностью понимаю, что публичные и частные члены на самом деле не существуют на языке Си. Однако, как и большинство программистов на C, я по-прежнему отношусь к членам как к публичным или частным, чтобы поддерживать дизайн ОО. В дополнение к типичным методам ОО, я обнаружил, что я следую шаблону (см. Пример ниже), который помогает мне различать, какие методы предназначены для внешнего мира, по сравнению с частными членами, которые могут иметь меньше проверок / более эффективны и т. Д. ... Существует ли стандарт или лучшая практика для такой вещи, или мой пример ниже - хороший способ приблизиться к этому?

Заголовок примера

#ifndef _MODULE_X_H_
#define _MODULE_X_H_

bool MOD_X_get_variable_x(void);
void MOD_X_set_variable_x(bool);

#endif /* _MODULE_X_H_ */

Пример источника

// Module Identifier: MOD_X 
#include "module_x.h"

// Private prototypes
static void mod_x_do_something_cool(void);
static void mod_x_do_something_else_cool(void);

// Private Variables
static bool var_x;

// Public Functions - Note the upper case module identifier
bool MOD_X_get_variable_x(void)      {return var_x;}
void MOD_X_set_variable_x(bool input){var_x = input;}

// Private Functions  - Note the lower case module identifier
void mod_x_do_something_cool(void){
     // Some incredibly cool sub routine 
}

void mod_x_do_something_else_cool(void){
     // Another incredibly cool sub routine 
}
Адам Льюис
источник
2
+1 За интересную тему: ОО дизайн реализован на С! Я бы следовал вашему подходу объявления публичных функций в заголовочном файле и приватных как статических функций в файле .c реализации. Я не уверен, почему вам нужно конкретное соглашение об именах. Почему бы не использовать, например, заглавные буквы для публичных и частных функций?
Джорджио
13
Бьярн Страуструп создал довольно всеобъемлющий способ написания объектно-ориентированных C ...
Муравей
Для другого интересного способа выполнения объектно-ориентированного программирования на C вы можете взглянуть на графический инструментарий Xt, знакомый программистам X11. Ссылка: en.wikipedia.org/wiki/X_Toolkit_Intrinsics
SDG
@ Джорджио: Точка верхнего и нижнего регистра для открытых и закрытых членов такова, что при просмотре кода или его обслуживании сразу же становится известно, является ли он открытым или закрытым без необходимости искать объявление.
Адам Льюис
@Ant: Objective-C - еще одна возможность. Я думаю, суть в том, что если вы программируете на C, вы все равно можете использовать OO design. Конечно, если я интенсивно использую ООП, я выбираю ОО язык.
Джорджио

Ответы:

17

Соглашение, которое я использую:

  • Открытая функция (в заголовочном файле):

    struct Classname;
    Classname_functionname(struct Classname * me, other args...);
  • Частная функция (статическая в файле реализации)

    static functionname(struct Classname * me, other args...)

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

Более того, OO-C делает способ передачи объекта в качестве первого аргумента.

mouviciel
источник
1
+1 Не большой эксперт по Си, но это выглядит солидно и правильно (даже в терминах инкапсуляции, которые я никогда не коррелировал с Си - до сих пор).
Ям Маркович
Остерегайтесь ограничений символов идентификаторов, установленных некоторыми компиляторами (например, 31 символов для некоторых!)
ловко
8

Обычно соглашение состоит в том, чтобы вообще не помещать закрытые функции в заголовок .

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

Если вам по какой-то причине нужно сделать функцию доступной для какого-то другого класса, но в остальном все еще закрытой, то вы называете ее так же, как любой другой метод, но помещаете ее в отдельный заголовок "-private".

То же самое относится и к определению типа. Если это возможно, вы только объявляете структуру как неполный тип в заголовке и определяете ее либо в источнике, либо в заголовке "-private". Вам нужно определение, чтобы наследовать класс, поэтому вы будете рассматривать дополнительный заголовок как защищенный, а не как личный объект.


Вероятно, самая большая часть объектно-ориентированного кода на C - это платформа Gnome. Вы можете легко увидеть соглашение о библиотеке GObject, которая предоставляет базовые классы самого низкого уровня . Это примерно то, что я описал выше и используется во всем Gnome.

Ян Худек
источник
Рад, что вы затронули тот факт, что символ не будет виден за пределами блока компиляции. Меня осенило после разговора с коллегами на эту тему. Однако для пояснения приватных функций нет в заголовочном файле, они статически объявлены в C-файле.
Адам Льюис
-1

Если фактический «класс» существует, в форме структуры, непрозрачного типа или подобного, то я называю его в соответствии с:

typedef struct classname_t classname_t; 

Суффикс _t - это очень распространенное соглашение по именованию в C, используемое самим стандартом C. Менее распространенным является использование заглавной буквы для классов / типов.

Следующее, что вы делаете, это придумываете префикс именования для всех публичных функций. Как правило, некоторые 3 буквы. Все функции, принадлежащие к «яблочному классу», возможно, будут названы app_set_something()и app_get_something()т. Д.

Тогда вы захотите использовать согласованное соглашение об именах. «Конструктор» может быть назван app_init()или app_construct(), то «деструктор app_clear(), app_destruct(), app_destroy()или аналогичный. Используйте те же правила именования для всех классов. Затем сделать то же самое для функций сеттер / добытчика, и так далее.

Приватные (статические) функции на самом деле не нуждаются в префиксе класса, так как они все равно недоступны вне файла .c. Вы могли бы по-прежнему дать им тот же префикс по соображениям согласованности, или, возможно, просто назвать их все с частным префиксом, например private_func(). Очень распространенный способ - дать им имена, начинающиеся с подчеркивания, но это плохо, так как может конфликтовать с библиотечными функциями. Строго говоря, вы не можете использовать идентификаторы, начинающиеся с подчеркивания.

Я бы не рекомендовал использовать верхний регистр как способ различения частного и публичного. Практически во всех стандартах C-кодирования принято, что все буквы в верхнем регистре обозначают константу, макрос или определение препроцессора. Это соглашение используется самим стандартом C, Windows API, ядром Linux и так далее.


источник
_t зарезервировано.
Река Лилит