14

Short Question
Is there a typical way to name 'public' and 'private' members of an OO C project?

Background
I fully understand that public and private members do not really exist in the C language. However, like most C programmers, I still treat members as public or private to maintain the OO design. In addition to the typical OO methods I have found my self following a pattern (see example below) that makes it easier for me to distinguish which methods are meant for the outside world vs the private members that may have fewer checks / are more efficient etc... Does a standard or best practice exist for such a thing or is my example below a good way to approach this?

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

Example Source

// 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 
}

3 Answers3

18

The convention I use is:

  • Public function (in header file):

    struct Classname;
    Classname_functionname(struct Classname * me, other args...);
    
  • Private function (static in implementation file)

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

Don't focus on case. The point is to distinguish two public methods from two classes by prepending a prefix (class name in this convention).

Moreover, what makes OO-C is the way the object is passed as first argument.

mouviciel
  • 15,491
9

Usually the convention is to not put the private functions in the header at all.

Since you normally put implementation of one object wholly in one source, the private function can usually be just file-static. In that case you'd usually skip the prefix to save some typing (the symbol won't be visible outside of that compilation unit).

If you for some reason need to make the function available to some other class, but otherwise still private, than you name it just like any other method, but put it in a separate "-private" header.

The same applies to the definition of the type too. If possible, you only forward-declare the structure as incomplete type in the header and define it either in the source or in the "-private" header. You need the definition to inherit the class, so you'd treat the extra header as protected rather than private stuff than.


Probably the biggest piece of object-oriented code in C is the Gnome platform. You can most easily see the convention on the GObject library, that provides the lowest level base classes. It it roughly what I describe above and is used throughout Gnome.

Jan Hudec
  • 18,410
-1

If an actual "class" exists, in the form of a struct, opaque type or similar, then I name it according to:

typedef struct classname_t classname_t; 

The _t suffix is a very common naming convention in C, used by the C standard itself. Less common is to use a capital letter for classes/types.

The next thing you do is to come up with a naming prefix for all public functions. Typically some 3 letter thing. All functions belonging to the "apple class" would perhaps be named app_set_something(), app_get_something() etc.

Then you will want to use a consistent naming convention. The "constructor" could be named app_init() or app_construct(), the "destructor app_clear(), app_destruct(), app_destroy() or similar. Use the same naming convention for all your classes. Then do the same for setter/getter functions, and so on.

Private (static) functions don't really need a class prefix since they aren't accessible outside the .c file anyhow. You could still give them the same prefix for consistency reasons, or perhaps simply name them all with a private prefix, such as private_func(). A very common way is to give them names starting with an underscore, but this is bad since it may collide with library functions. Strictly speaking you aren't allowed to use identifiers starting with an underscore.

I would not recommend to use upper case as a way to distinguish between private and public. The convention in almost all C coding standards is that all letters upper case indicates a constant, macro or a pre-processor define. That convention is used by the C standard itself, by the Windows API, by the Linux kernel and so on.