Was sind die typischen Namenskonventionen für öffentliche und private OO C-Funktionen? [geschlossen]

12

Kurze Frage
Gibt es eine typische Möglichkeit, "öffentliche" und "private" Mitglieder eines OO C-Projekts zu benennen?

Hintergrund
Ich verstehe voll und ganz, dass öffentliche und private Mitglieder in der C-Sprache nicht wirklich existieren. Wie die meisten C-Programmierer behandle ich Mitglieder jedoch weiterhin als öffentlich oder privat, um das OO-Design beizubehalten. Zusätzlich zu den typischen OO-Methoden habe ich mich nach einem Muster wiedergefunden (siehe Beispiel unten), das es mir erleichtert, zu unterscheiden, welche Methoden für die Außenwelt gedacht sind , und welche privaten Mitglieder möglicherweise weniger Prüfungen haben / effizienter sind usw. ... Gibt es für so etwas einen Standard oder eine Best Practice oder ist mein Beispiel unten ein guter Weg, dies zu erreichen?

Beispiel-Header

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

Beispielquelle

// 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
quelle
2
+1 Für das interessante Thema: OO-Design in C implementiert! Ich würde Ihrem Ansatz folgen, öffentliche Funktionen in der Header-Datei und private als statische Funktionen in der Implementierungs-C-Datei zu deklarieren. Ich bin mir nicht sicher, warum Sie eine bestimmte Namenskonvention benötigen. Warum nicht z. B. Großbuchstaben für öffentliche und private Funktionen verwenden?
Giorgio
13
Bjarne Stroustrup hat eine ziemlich umfassende Art des Schreibens objektorientierter C ...
Ant
Eine weitere interessante Möglichkeit zur objektbasierten Programmierung in C finden Sie im Xt-Grafik-Toolkit, das X11-Programmierern vertraut ist. Ref: en.wikipedia.org/wiki/X_Toolkit_Intrinsics
sdg
@Giorgio: Der Punkt zwischen Groß- und Kleinschreibung für öffentliche und private Mitglieder ist, dass bei der Überprüfung des Codes oder der Pflege des Codes auf einen Blick bekannt ist, ob er öffentlich oder privat ist, ohne nach einer Erklärung suchen zu müssen.
Adam Lewis
@Ant: Objective-C ist eine weitere Möglichkeit. Ich denke, der Punkt hier ist, dass Sie, wenn Sie in C programmieren, immer noch OO-Design verwenden können. Wenn ich OOP stark benutze, greife ich natürlich zu einer OO-Sprache.
Giorgio

Antworten:

17

Die Konvention, die ich benutze, ist:

  • Öffentliche Funktion (in der Header-Datei):

    struct Classname;
    Classname_functionname(struct Classname * me, other args...);
  • Private Funktion (statisch in Implementierungsdatei)

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

Konzentriere dich nicht auf den Fall. Es geht darum, zwei öffentliche Methoden von zwei Klassen zu unterscheiden, indem ein Präfix (Klassenname in dieser Konvention) vorangestellt wird.

Darüber hinaus macht OO-C die Art und Weise aus, wie das Objekt als erstes Argument übergeben wird.

Mouviciel
quelle
1
+1 Kein großer C-Experte, aber das sieht solide und korrekt aus (auch in Bezug auf die Kapselung, die ich bisher nie mit C korreliert habe).
Yam Marcovic
Beachten Sie die von einigen Compilern erzwungenen Beschränkungen für Bezeichnerzeichen (z. B. 31 Zeichen für einige!)
halten Sie den
8

Normalerweise besteht die Konvention darin , die privaten Funktionen überhaupt nicht in den Header zu setzen .

Da Sie normalerweise die Implementierung eines Objekts vollständig in einer Quelle ablegen, kann die private Funktion normalerweise nur dateistatisch sein. In diesem Fall überspringen Sie normalerweise das Präfix, um einige Eingaben zu speichern (das Symbol ist außerhalb dieser Kompilierungseinheit nicht sichtbar).

Wenn Sie die Funktion aus irgendeinem Grund einer anderen Klasse zur Verfügung stellen müssen, aber ansonsten immer noch privat sind, benennen Sie sie wie jede andere Methode, setzen Sie sie jedoch in einen separaten "-privaten" Header.

Gleiches gilt auch für die Definition des Typs. Wenn möglich, deklarieren Sie die Struktur nur als unvollständigen Typ im Header und definieren sie entweder im Quell- oder im "-privaten" Header. Sie benötigen die Definition, um die Klasse zu erben, sodass Sie den zusätzlichen Header eher als geschützt als als privat behandeln würden.


Der wahrscheinlich größte objektorientierte Code in C ist die Gnome-Plattform. Sie können die Konvention am einfachsten in der GObject-Bibliothek sehen, die die Basisklassen der niedrigsten Ebene bereitstellt . Es ist ungefähr das, was ich oben beschrieben habe und wird in Gnome verwendet.

Jan Hudec
quelle
Ich bin froh, dass Sie die Tatsache angesprochen haben, dass das Symbol außerhalb der Kompilierungseinheit nicht sichtbar ist. Es wurde mir klar, nachdem ich mit einigen Mitarbeitern über dieses Thema gesprochen hatte. Um zu verdeutlichen, dass sich die privaten Funktionen nicht in der Header-Datei befinden, werden sie statisch in der C-Datei deklariert.
Adam Lewis
-1

Wenn eine tatsächliche "Klasse" in Form einer Struktur, eines undurchsichtigen Typs oder ähnlichem existiert, benenne ich sie wie folgt:

typedef struct classname_t classname_t; 

Das Suffix _t ist eine sehr häufige Namenskonvention in C, die vom C-Standard selbst verwendet wird. Weniger verbreitet ist die Verwendung eines Großbuchstabens für Klassen / Typen.

Als nächstes müssen Sie ein Namenspräfix für alle öffentlichen Funktionen erstellen. Normalerweise eine 3-Buchstaben-Sache. Alle Funktionen zum „Apfel - Klasse“ gehören , vielleicht nennen würde app_set_something(), app_get_something()usw.

Dann möchten Sie eine konsistente Namenskonvention verwenden. Der „Konstruktor“ könnte genannt werden app_init()oder app_construct()die „destructor app_clear(), app_destruct(), app_destroy()oder ähnliches. Verwenden Sie die gleiche Namenskonvention für alle Klassen. Dann das gleiche tun für Setter / Getter - Funktionen, und so weiter.

Private (statische) Funktionen benötigen kein Klassenpräfix, da sie außerhalb der C-Datei sowieso nicht verfügbar sind. Sie können ihnen aus Konsistenzgründen immer noch dasselbe Präfix geben oder sie einfach alle mit einem privaten Präfix benennen, z private_func(). Eine sehr häufige Methode besteht darin, ihnen Namen zu geben, die mit einem Unterstrich beginnen. Dies ist jedoch schlecht, da sie möglicherweise mit Bibliotheksfunktionen kollidieren. Genau genommen dürfen Sie keine Bezeichner verwenden, die mit einem Unterstrich beginnen.

Ich würde nicht empfehlen, Großbuchstaben zu verwenden, um zwischen privat und öffentlich zu unterscheiden. Die Konvention in fast allen C-Codierungsstandards ist, dass alle Großbuchstaben eine Konstante, ein Makro oder eine Vorprozessordefinition angeben. Diese Konvention wird vom C-Standard selbst, von der Windows-API, vom Linux-Kernel usw. verwendet.


quelle
_t ist reserviert.
Lilith River