¿Cuáles son las convenciones de nomenclatura típicas para las funciones públicas y privadas de OO C? [cerrado]

12

Pregunta corta
¿Existe una forma típica de nombrar miembros 'públicos' y 'privados' de un proyecto OO C?

Antecedentes
Entiendo completamente que los miembros públicos y privados realmente no existen en el lenguaje C. Sin embargo, como la mayoría de los programadores de C, todavía trato a los miembros como públicos o privados para mantener el diseño OO. Además de los métodos típicos de OO, me he encontrado siguiendo un patrón (ver ejemplo a continuación) que me hace más fácil distinguir qué métodos están destinados al mundo exterior frente a los miembros privados que pueden tener menos controles / son más eficientes, etc. ... ¿Existe un estándar o una mejor práctica para tal cosa o mi ejemplo a continuación es una buena manera de abordar esto?

Encabezado de ejemplo

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

Fuente de ejemplo

// 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
fuente
2
+1 Para el tema interesante: diseño OO implementado en C! Seguiría su enfoque de declarar las funciones públicas en el archivo de encabezado y las privadas como funciones estáticas en el archivo .c de implementación. Sin embargo, no estoy seguro de por qué necesita una convención de nomenclatura particular. ¿Por qué no utilizar, por ejemplo, mayúsculas para funciones públicas y privadas?
Giorgio
13
Bjarne Stroustrup armó una manera bastante completa de escribir orientado a objetos C ...
Ant
Para otra forma interesante de hacer programación basada en objetos en C, puede consultar el kit de herramientas gráficas Xt, familiar para los programadores X11. Ref: en.wikipedia.org/wiki/X_Toolkit_Intrinsics
sdg
@Giorgio: El objetivo de las mayúsculas y minúsculas para los miembros públicos y privados es que, al revisar el código o mantener el código, se sabe de un vistazo si es público o privado sin tener que buscar una declaración.
Adam Lewis
@Ant: Objective-C es otra posibilidad. Creo que el punto aquí es que si está programando en C todavía puede usar el diseño OO. Por supuesto, si hago un uso intensivo de OOP, voy por un lenguaje OO.
Giorgio

Respuestas:

17

La convención que uso es:

  • Función pública (en archivo de encabezado):

    struct Classname;
    Classname_functionname(struct Classname * me, other args...);
    
  • Función privada (estática en el archivo de implementación)

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

No te concentres en el caso. El punto es distinguir dos métodos públicos de dos clases anteponiendo un prefijo (nombre de clase en esta convención).

Además, lo que hace que OO-C sea la forma en que se pasa el objeto como primer argumento.

Mouviciel
fuente
1
+1 No es un gran experto en C, pero eso parece sólido y correcto (incluso en términos de encapsulación, que nunca correlacioné con C, hasta ahora).
Yam Marcovic
Tenga cuidado con los límites de caracteres identificadores impuestos por algunos compiladores (por ejemplo, ¡31 caracteres para algunos!)
detly
8

Por lo general, la convención es no poner las funciones privadas en el encabezado en absoluto .

Como normalmente coloca la implementación de un objeto completamente en una fuente, la función privada generalmente puede ser simplemente estática de archivo. En ese caso, generalmente omitiría el prefijo para guardar algo de escritura (el símbolo no será visible fuera de esa unidad de compilación).

Si por alguna razón necesita hacer que la función esté disponible para alguna otra clase, pero por lo demás sigue siendo privada, puede nombrarla como cualquier otro método, pero ponerla en un encabezado "-privado" separado.

Lo mismo se aplica a la definición del tipo también. Si es posible, solo declara hacia adelante la estructura como tipo incompleto en el encabezado y la define en el origen o en el encabezado "-privado". Necesita la definición para heredar la clase, por lo que trataría el encabezado adicional como algo protegido en lugar de privado.


Probablemente la pieza más grande de código orientado a objetos en C es la plataforma Gnome. Puede ver más fácilmente la convención en la biblioteca GObject, que proporciona las clases base de nivel más bajo . Es más o menos lo que describo anteriormente y se usa en todo Gnome.

Jan Hudec
fuente
Me alegra que haya tocado el hecho de que el símbolo no será visible fuera de la unidad de compilación. Me di cuenta después de hablar con algunos compañeros de trabajo sobre este tema. Sin embargo, para aclarar que las funciones privadas no están en el archivo de encabezado, se declaran estáticamente en el archivo C.
Adam Lewis
-1

Si existe una "clase" real, en forma de estructura, tipo opaco o similar, entonces lo nombro de acuerdo con:

typedef struct classname_t classname_t; 

El sufijo _t es una convención de nomenclatura muy común en C, utilizada por el estándar C en sí. Menos común es usar una letra mayúscula para clases / tipos.

Lo siguiente que debe hacer es crear un prefijo de nombre para todas las funciones públicas. Típicamente algo de 3 letras. Todas las funciones que pertenecen a la "clase de manzana" quizás se denominen app_set_something(), app_get_something()etc.

Entonces querrás usar una convención de nomenclatura consistente. El "constructor" podría ser nombrado app_init()o app_construct(), el "destructor app_clear(), app_destruct(), app_destroy()o similar. Utilice la misma convención de nombres para todas sus clases. Luego hacer lo mismo para las funciones setter / getter, y así sucesivamente.

Las funciones privadas (estáticas) realmente no necesitan un prefijo de clase, ya que de todos modos no son accesibles fuera del archivo .c. Todavía podría darles el mismo prefijo por razones de coherencia, o tal vez simplemente nombrarlos a todos con un prefijo privado, como private_func(). Una forma muy común es darles nombres que comiencen con un guión bajo, pero esto es malo ya que puede chocar con las funciones de la biblioteca. Estrictamente hablando, no puedes usar identificadores que comiencen con un guión bajo.

No recomendaría usar mayúsculas como una forma de distinguir entre privado y público. La convención en casi todos los estándares de codificación C es que todas las letras mayúsculas indican una definición constante, macro o de preprocesador. Esa convención es utilizada por el estándar C en sí, por la API de Windows, por el kernel de Linux, etc.


fuente
_t está reservado.
Lilith River