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 
}
Adam Lewis
  • 543
  • 4
  • 12
  • 2
    +1 For the interesting topic: OO design implemented in C! I would follow your approach of declaring public functions in the header file and private ones as static functions in the implementation .c file. I am not sure why you need a particular naming convention though. Why not use, e.g., uppercase for both public and private functions? – Giorgio Oct 21 '11 at 10:09
  • 13
    Bjarne Stroustrup put together a pretty comprehensive way of writing object-oriented C... – Ant Oct 21 '11 at 12:20
  • For another interesting way of doing Object-based programming in C you can look at the Xt graphics toolkit, familiar to X11 programmers. Ref: http://en.wikipedia.org/wiki/X_Toolkit_Intrinsics – sdg Oct 21 '11 at 12:30
  • @Giorgio: The point of the upper vs lower case for public and private members is so that when reviewing the code or maintaining the code it is known at a glance if its public or private without having to search for a declaration. – Adam Lewis Oct 21 '11 at 15:04
  • @Ant: Objective-C is another possibility. I think the point here is that if you are programming in C you can still use OO design. Of course if I make heavy use of OOP I go for an OO language. – Giorgio Oct 21 '11 at 16:29
  • Object-oriented C is not a new topic, people have been writing OO programs in C since the mid 80s. There is an old book "Object-oriented programming with ANSI-C" released 1990. So, nothing new or exciting here. If you believe that you must use C++ to write object-oriented programs, I'm afraid that you don't quite grasp what OO programming means. C++ merely makes OO design easier: a program written in C++ doesn't automatically get an OO design. That discussion is very old, so please just search this site or SO, there's likely at least 100 such discussions already archived. –  Aug 22 '12 at 12:57
  • @Lundin: OMT is 20 years old and discusses the possibility of implementing OO designs in different languages, including non-OO languages like C. The idiea is to clearly separate design from implementation and not just design while you code. And of course, as you pointed out, using an OO-language does not guarantee that your design is OO. – Giorgio Aug 22 '12 at 13:35

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,473
  • 1
  • 37
  • 64
  • 1
    +1 Not a big C expert, but that looks solid and correct (even in encapsulation terms, which I never correlated with C - until now). – Yam Marcovic Oct 22 '11 at 23:07
  • Beware of the identifier character limits enforced by some compilers (eg. 31 characters for some!) – detly Aug 23 '12 at 05:12
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,250
  • 1
  • 39
  • 62
  • Glad you touched on the fact that the symbol won't be visible outside of the compilation unit. It dawned on me after talking with some co-workers about this topic. However to clarify the private functions are *not* in the header file, they are declared staticly in the C file. – Adam Lewis Oct 24 '11 at 15:02
-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.