Quais são as convenções de nomenclatura típicas para funções públicas e privadas do OO C? [fechadas]

12

Pergunta curta
Existe uma maneira típica de nomear membros 'públicos' e 'privados' de um projeto OO C?

Antecedentes
Entendo perfeitamente que os membros públicos e privados não existem realmente na linguagem C. No entanto, como a maioria dos programadores em C, eu ainda trato os membros como públicos ou privados para manter o design do OO. Além dos métodos típicos de OO, encontrei-me seguindo um padrão (veja o exemplo abaixo) que facilita para mim distinguir quais métodos se destinam ao mundo exterior versus os membros privados que podem ter menos verificações / são mais eficientes etc. ... Existe uma norma ou prática recomendada para tal coisa ou o meu exemplo abaixo é uma boa maneira de abordar isso?

Cabeçalho de exemplo

#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_ */

Fonte de exemplo

// 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 
}
Adam Lewis
fonte
2
+1 Para o tópico interessante: Design de OO implementado em C! Eu seguiria sua abordagem de declarar funções públicas no arquivo de cabeçalho e privadas como funções estáticas no arquivo .c de implementação. Não sei por que você precisa de uma convenção de nomenclatura específica. Por que não usar, por exemplo, maiúsculas para funções públicas e privadas?
Giorgio
13
Bjarne Stroustrup juntos uma forma bastante abrangente de escrever orientada a objetos C ...
Ant
Para outra maneira interessante de fazer a programação baseada em objetos em C, você pode ver o kit de ferramentas de gráficos Xt, familiar aos programadores do X11. Ref: pt.wikipedia.org/wiki/X_Toolkit_Intrinsics
sdg
@Giorgio: O objetivo das letras maiúsculas e minúsculas para membros públicos e privados é para que, ao revisar o código ou mantê-lo, seja conhecido rapidamente se é público ou privado sem precisar procurar uma declaração.
Adam Lewis
@ Ant: Objective-C é outra possibilidade. Acho que o ponto aqui é que, se você estiver programando em C, ainda poderá usar o design OO. É claro que, se eu fizer uso pesado de OOP, vou para um idioma OO.
Giorgio

Respostas:

17

A convenção que uso é:

  • Função pública (no arquivo de cabeçalho):

    struct Classname;
    Classname_functionname(struct Classname * me, other args...);
    
  • Função privada (estática no arquivo de implementação)

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

Não se concentre no caso. O objetivo é distinguir dois métodos públicos de duas classes, acrescentando um prefixo (nome da classe nesta convenção).

Além disso, o que torna OO-C é a maneira como o objeto é passado como primeiro argumento.

mouviciel
fonte
1
+1 Não é um grande especialista em C, mas parece sólido e correto (mesmo em termos de encapsulamento, que eu nunca correlacionei com C - até agora).
Yam Marcovic
Cuidado com os limites de caracteres identificador impostas por alguns compiladores (por exemplo, 31 caracteres para alguns.!)
detly
8

Normalmente, a convenção é não colocar as funções privadas no cabeçalho .

Como você normalmente coloca a implementação de um objeto totalmente em uma fonte, a função privada geralmente pode ser apenas estática no arquivo. Nesse caso, você costuma pular o prefixo para salvar algumas digitações (o símbolo não estará visível fora dessa unidade de compilação).

Se, por algum motivo, você precisar disponibilizar a função para alguma outra classe, mas ainda assim privada, você o nomeará como qualquer outro método, mas coloque-o em um cabeçalho "-private" separado.

O mesmo se aplica à definição do tipo também. Se possível, você apenas declara a estrutura como tipo incompleto no cabeçalho e define-a na fonte ou no cabeçalho "-private". Você precisa da definição para herdar a classe, portanto, trataria o cabeçalho extra como protegido e não como material particular.


Provavelmente, o maior pedaço de código orientado a objetos em C é a plataforma Gnome. Você pode ver com mais facilidade a convenção na biblioteca GObject, que fornece as classes base de nível mais baixo . É basicamente o que eu descrevi acima e é usado em todo o Gnome.

Jan Hudec
fonte
Que bom que você tocou no fato de que o símbolo não será visível fora da unidade de compilação. Me ocorreu depois de conversar com alguns colegas de trabalho sobre esse tópico. No entanto, para esclarecer que as funções privadas não estão no arquivo de cabeçalho, elas são declaradas estática no arquivo C.
Adam Lewis
-1

Se existe uma "classe" real, na forma de uma estrutura, tipo opaco ou similar, então o nomeio de acordo com:

typedef struct classname_t classname_t; 

O sufixo _t é uma convenção de nomenclatura muito comum em C, usada pelo próprio padrão C. Menos comum é usar uma letra maiúscula para classes / tipos.

A próxima coisa que você faz é criar um prefixo de nomenclatura para todas as funções públicas. Normalmente, algo com três letras. Talvez todas as funções pertencentes à "classe apple" sejam nomeadas app_set_something(), app_get_something()etc.

Então você vai querer usar uma convenção de nomenclatura consistente. O "construtor" pode ser nomeado app_init()ou app_construct(), o "destructor app_clear(), app_destruct(), app_destroy()ou similar. Use a mesma convenção de nomenclatura para todas as suas classes. Em seguida, faça o mesmo para funções setter / getter, e assim por diante.

Funções privadas (estáticas) realmente não precisam de um prefixo de classe, pois não são acessíveis fora do arquivo .c. Você ainda pode dar a eles o mesmo prefixo por motivos de consistência, ou talvez simplesmente nomeá-los todos com um prefixo particular, como private_func(). Uma maneira muito comum é dar nomes a eles começando com um sublinhado, mas isso é ruim, pois pode colidir com as funções da biblioteca. A rigor, você não tem permissão para usar identificadores começando com um sublinhado.

Eu não recomendaria usar maiúsculas como uma maneira de distinguir entre privado e público. A convenção em quase todos os padrões de codificação C é que todas as letras maiúsculas indicam uma constante, macro ou um pré-processador definido. Essa convenção é usada pelo próprio padrão C, pela API do Windows, pelo kernel do Linux e assim por diante.


fonte
_t está reservado.
Lilith River