Quali sono le convenzioni di denominazione tipiche per le funzioni pubbliche e private di OO C? [chiuso]


12

Breve domanda
Esiste un modo tipico di nominare membri "pubblici" e "privati" di un progetto OO C?

Contesto
Sono pienamente consapevole che i membri pubblici e privati ​​non esistono realmente nel linguaggio C. Tuttavia, come la maggior parte dei programmatori C, continuo a trattare i membri come pubblici o privati ​​per mantenere il design OO. Oltre ai tipici metodi OO, ho trovato me stesso seguendo uno schema (vedi esempio sotto) che mi rende più facile distinguere quali metodi sono destinati al mondo esterno rispetto ai membri privati ​​che possono avere meno controlli / sono più efficienti ecc. ... Esiste una prassi standard o migliore per una cosa del genere o il mio esempio di seguito è un buon modo per affrontarlo?

Esempio di intestazione

#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 di esempio

// 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 Per l'argomento interessante: progettazione OO implementata in C! Seguirei il tuo approccio nel dichiarare le funzioni pubbliche nel file di intestazione e quelle private come funzioni statiche nel file .c di implementazione. Non sono sicuro del motivo per cui è necessaria una particolare convenzione di denominazione. Perché non utilizzare, ad esempio, maiuscole per le funzioni sia pubbliche che private?
Giorgio,

13
Bjarne Stroustrup ha messo insieme un modo abbastanza completo di scrivere orientato agli oggetti C ...
Ant

Per un altro modo interessante di eseguire la programmazione basata su oggetti in C, puoi guardare il toolkit grafico Xt, familiare ai programmatori X11. Rif: en.wikipedia.org/wiki/X_Toolkit_Intrinsics
sdg

@Giorgio: il punto in maiuscolo vs minuscolo per i membri pubblici e privati ​​è che quando si rivede il codice o si mantiene il codice è noto a colpo d'occhio se il suo pubblico o privato senza dover cercare una dichiarazione.
Adam Lewis,

@Ant: Objective-C è un'altra possibilità. Penso che il punto qui sia che se stai programmando in C puoi ancora usare OO design. Ovviamente se faccio un uso intenso di OOP, scelgo una lingua OO.
Giorgio,

Risposte:


17

La convenzione che utilizzo è:

  • Funzione pubblica (nel file di intestazione):

    struct Classname;
    Classname_functionname(struct Classname * me, other args...);
    
  • Funzione privata (statica nel file di implementazione)

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

Non concentrarti sul caso. Il punto è distinguere due metodi pubblici da due classi anteponendo un prefisso (nome della classe in questa convenzione).

Inoltre, ciò che rende OO-C è il modo in cui l'oggetto viene passato come primo argomento.


1
+1 Non un grande esperto di C, ma sembra solido e corretto (anche in termini di incapsulamento, che non ho mai correlato con C - fino ad ora).
Yam Marcovic,

Fai attenzione ai limiti dei caratteri identificativi applicati da alcuni compilatori (ad es. 31 caratteri per alcuni!)
detly

8

Di solito la convenzione è di non mettere affatto le funzioni private nell'intestazione .

Dal momento che normalmente si mette l'implementazione di un oggetto interamente in una fonte, la funzione privata di solito può essere solo file-static. In tal caso di solito salteresti il ​​prefisso per salvare un po 'di battitura (il simbolo non sarà visibile al di fuori di quell'unità di compilazione).

Se per qualche motivo hai bisogno di rendere la funzione disponibile per un'altra classe, ma per il resto ancora privata, allora la chiami proprio come qualsiasi altro metodo, ma la metti in un'intestazione separata "-private".

Lo stesso vale per la definizione del tipo. Se possibile, dichiarare in avanti solo la struttura come tipo incompleto nell'intestazione e definirla nell'origine o nell'intestazione "-private". Hai bisogno della definizione per ereditare la classe, quindi tratteresti l'intestazione aggiuntiva come protetta anziché come privata.


Probabilmente il più grande pezzo di codice orientato agli oggetti in C è la piattaforma Gnome. Puoi facilmente vedere la convenzione sulla libreria GObject, che fornisce le classi base di livello più basso . È più o meno quello che descrivo sopra e viene usato in Gnome.


Sono contento che tu abbia toccato il fatto che il simbolo non sarà visibile al di fuori dell'unità di compilazione. Mi sono reso conto dopo aver parlato con alcuni colleghi di questo argomento. Tuttavia, per chiarire che le funzioni private non si trovano nel file di intestazione, vengono dichiarate staticamente nel file C.
Adam Lewis,

-1

Se esiste una vera "classe", sotto forma di una struttura, un tipo opaco o simile, allora la chiamo in base a:

typedef struct classname_t classname_t; 

Il suffisso _t è una convenzione di denominazione molto comune in C, utilizzata dallo standard C stesso. Meno comune è usare una lettera maiuscola per classi / tipi.

La prossima cosa da fare è trovare un prefisso di denominazione per tutte le funzioni pubbliche. In genere qualcosa di 3 lettere. Tutte le funzioni appartenenti alla "classe di mele" potrebbero forse essere nominate app_set_something(), app_get_something()ecc.

Quindi vorrai utilizzare una convenzione di denominazione coerente. Il "costruttore" potrebbe essere nominato app_init()o app_construct(), il "distruttore app_clear(), app_destruct(), app_destroy()o simili. Utilizzare la stessa convenzione di denominazione per tutte le classi. Poi fare lo stesso per le funzioni setter / getter, e così via.

Le funzioni private (statiche) non hanno davvero bisogno di un prefisso di classe poiché non sono comunque accessibili al di fuori del file .c. Potresti comunque dare loro lo stesso prefisso per motivi di coerenza, o forse semplicemente nominarli tutti con un prefisso privato, come private_func(). Un modo molto comune è quello di dare loro nomi che iniziano con un carattere di sottolineatura, ma questo è negativo poiché potrebbe scontrarsi con le funzioni della libreria. A rigor di termini non è consentito utilizzare identificatori che iniziano con un carattere di sottolineatura.

Non consiglierei di utilizzare le lettere maiuscole come modo per distinguere tra privato e pubblico. La convenzione in quasi tutti gli standard di codifica C è che tutte le lettere maiuscole indicano una costante, una macro o un pre-processore definito. Tale convenzione viene utilizzata dallo stesso standard C, dall'API di Windows, dal kernel Linux e così via.


_t è riservato.
Lilith River,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.