• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /* Minimal object-oriented facilities for C.
2    Copyright (C) 2006 Free Software Foundation, Inc.
3    Written by Bruno Haible <bruno@clisp.org>, 2006.
4 
5    This program is free software: you can redistribute it and/or modify
6    it under the terms of the GNU Lesser General Public License as published by
7    the Free Software Foundation; either version 2.1 of the License, or
8    (at your option) any later version.
9 
10    This program is distributed in the hope that it will be useful,
11    but WITHOUT ANY WARRANTY; without even the implied warranty of
12    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13    GNU Lesser General Public License for more details.
14 
15    You should have received a copy of the GNU Lesser General Public License
16    along with this program.  If not, see <https://www.gnu.org/licenses/>.  */
17 
18 /* This file defines minimal facilities for object-oriented programming
19    style in ANSI C.
20 
21    The facilities allow to define classes with single inheritance and
22    "virtual" methods.
23 
24    Strict type checking is provided in combination with a C++ compiler:
25    The code compiles in ANSI C with less strict type checking; when
26    compiled with a C++ compiler, strict type checking is done.
27 
28    In contrast to [OOC] and [OOPC], this implementation concentrates on the
29    bare essentials of an object-oriented programming style.  It does not
30    provide features that are "sometimes useful", but not essential.
31 
32    Features:
33      - Combination of fields and methods into a single object.      YES
34      - Description of objects of same shape and same behaviour
35        by a class.                                                  YES
36      - Single inheritance.                                          YES
37      - Multiple inheritance.                                        NO
38      - Operator overloading (compile-time polymorphism).            NO
39      - Virtual methods (run-time polymorphism).                     YES
40      - Information hiding: private/protected/public.         private fields
41      - Static fields and methods.                                   NO
42      - Constructors, destructors.                                   NO
43      - 'new', 'delete'.                                             NO
44      - Exception handling.                                          NO
45      - Garbage collection.                                          NO
46      - Templates / Generic classes with parameters.                 NO
47      - Namespaces.                                                  NO
48      - Hidden 'this' pointer in methods.                            NO
49      - Declaring or implementing several classes in the same file.  NO
50 
51    Rationale for NO:
52      - Multiple inheritance is not supported because programming languages
53        like Java and C# prove that they are not necessary. Modern design
54        patterns use delegation more often than composition; this reduces
55        the pressure to use multiple inheritance.
56        Multiple inheritance of "interfaces" (classes without fields) might
57        be considered, though.
58      - Operator overloading is not essential: The programmer can rename
59        methods so that they carry unambiguous method names. This also makes
60        the code more readable.
61      - Virtual methods are supported. Non-virtual methods are not: they
62        constitute an assumption about the possible subclasses which is more
63        often wrong than right. In other words, non-virtual methods are a
64        premature optimization - "the root of all evil", according to
65        Donald E. Knuth.
66      - Information hiding: 'protected' is not supported because it is always
67        inappropriate: it prohibits the use of the delegation design pattern.
68        'private' is implemented on fields. There are no 'public' fields,
69        since the use of getters/setters allows for overriding in subclasses
70        and is more maintainable (ability to set breakpoints). On the other
71        hand, all methods are 'public'. 'private` methods are not supported
72        because methods with static linkage can be used instead.
73      - Static fields and methods are not supported because normal variables
74        and functions with static or extern linkage can be used instead.
75      - Constructors and destructors are not supported.  The programmer can
76        define 'init' and 'do_free' methods himself.
77      - 'new', 'delete' are not supported because they only provide the
78        grouping of two lines of code into a single line of code.
79      - Exception handling is not supported because conventions with a return
80        code can be used instead.
81      - Garbage collection is not supported. Without it the programmer's life
82        is harder, but not impossible. The programmer has to think about
83        ownership of objects.
84      - Templates / Generic classes with parameters are not supported because
85        they are mostly used for container classes, and container classes can
86        be implemented in a simpler object-oriented way that requires only a
87        very limited form of class inheritance.
88      - Namespaces are not implemented, because they can be simulated by a
89        consistent naming convention.
90      - A hidden 'this' pointer in methods is not implemented. It reduces the
91        transparency of the code (because what looks like a variable access can
92        be an access through 'this') and is simply not needed.
93      - Declaring or implementing several classes in the same file is not
94        supported, because it is anyway good practice to define each class in
95        its own .oo.h / .oo.c file.
96 
97    Syntax:
98 
99    The syntax resembles C++, but deviates from C++ where the C++ syntax is
100    just too braindead.
101 
102    A root class is declared in a .oo.h file:
103 
104      struct rootfoo
105      {
106      methods:
107        int method1 (rootfoo_t x, ...); ...
108      };
109 
110    and in the corresponding .oo.c file:
111 
112      struct rootfoo
113      {
114      fields:
115        int field1; ...
116      };
117 
118    A subclass is declared in a .oo.h file as well:
119 
120      struct subclass : struct rootfoo
121      {
122      methods:
123        int method2 (subclass_t x, ...); ...
124      };
125 
126    and in the corresponding .oo.c file:
127 
128      struct subclass : struct rootfoo
129      {
130      fields:
131        int field2; ...
132      };
133 
134    This defines:
135      - An incomplete type 'struct any_rootfoo_representation' or
136        'struct subclass_representation', respectively. It denotes the memory
137        occupied by an object of the respective class. The prefix 'any_' is
138        present only for a root class.
139      - A type 'rootfoo_t' or 'subclass_t' that is equivalent to a pointer
140        'struct any_rootfoo_representation *' or
141        'struct subclass_representation *', respectively.
142      - A type 'struct rootfoo_implementation' or
143        'struct subclass_implementation', respectively. It contains a virtual
144        function table for the corresponding type.
145      - A type 'struct rootfoo_representation_header' or
146        'struct subclass_representation_header', respectively, that defines
147        the part of the memory representation containing the virtual function
148        table pointer.
149      - Functions 'rootfoo_method1 (rootfoo_t x, ...);' ...
150                  'subclass_method1 (subclass_t x, ...);' ...
151                  'subclass_method2 (subclass_t x, ...);' ...
152        that invoke the corresponding methods. They are realized as inline
153        functions if possible.
154      - A declaration of 'rootfoo_typeinfo' or 'subclass_typeinfo', respectively,
155        each being a typeinfo_t instance.
156      - A declaration of 'ROOTFOO_SUPERCLASSES' or 'SUBCLASS_SUPERCLASSES',
157        respectively, each being an initializer for an array of typeinfo_t.
158      - A declaration of 'ROOTFOO_SUPERCLASSES_LENGTH' or
159        'SUBCLASS_SUPERCLASSES_LENGTH', respectively, each denoting the length
160        of that initializer.
161      - A declaration of 'rootfoo_vtable' or 'subclass_vtable', respectively,
162        being an instance of 'struct rootfoo_implementation' or
163        'struct subclass_implementation', respectively.
164      - A header file "rootfoo.priv.h" or "subclass.priv.h" that defines the
165        private fields of 'struct rootfoo_representation' or
166        'struct subclass_representation', respectively.
167 
168    A class implementation looks like this, in a .oo.c file:
169 
170      struct subclass : struct rootfoo
171      {
172      fields:
173        int field2; ...
174      };
175 
176      int subclass::method1 (subclass_t x, ...) { ... } [optional]
177      int subclass::method2 (subclass_t x, ...) { ... }
178      ...
179 
180    At the place of the second "struct subclass" definition, the type
181    'struct subclass_representation' is expanded, and the macro 'super' is
182    defined, referring to the vtable of the superclass. For root classes,
183    'super' is not defined. Also, 'subclass_typeinfo' is defined.
184 
185    Each method subclass::method_i defines the implementation of a method
186    for the particular class. Its C name is subclass__method_i (not to be
187    confused with subclass_method_i, which is the externally visible function
188    that invokes this method).
189 
190    Methods that are not defined implicitly inherited from the superclass.
191 
192    At the end of the file, 'subclass_vtable' is defined, as well as
193      'subclass_method1 (subclass_t x, ...);' ...
194      'subclass_method2 (subclass_t x, ...);' ...
195    if they were not already defined as inline functions in the header file.
196 
197    Object representation in memory:
198      - Objects have as their first field, called 'vtable', a pointer to a table
199        to data and function pointers that depend only on the class, not on the
200        object instance.
201      - One of the first fields of the vtable is a pointer to the
202        'superclasses'; this is a NULL-terminated array of pointers to
203        typeinfo_t objects, starting with the class itself, then its
204        superclass etc.
205 
206 
207    [OOC] Axel-Tobias Schreiner: Object-oriented programming with ANSI-C. 1993.
208 
209    [OOPC] Laurent Deniau: Object Oriented Programming in C. 2001.
210 
211  */
212 
213 #ifndef _MOO_H
214 #define _MOO_H
215 
216 /* Get size_t, abort().  */
217 #include <stdlib.h>
218 
219 /* An object of this type is defined for each class.  */
220 typedef struct
221 {
222   const char *classname;
223 } typeinfo_t;
224 
225 /* IS_INSTANCE (OBJ, ROOTCLASSNAME, CLASSNAME)
226    tests whether an object is instance of a given class, given as lower case
227    class name.  */
228 #define IS_INSTANCE(obj,rootclassname,classname) \
229   (((const struct rootclassname##_representation_header *)(const struct any_##rootclassname##_representation *)(obj))->vtable->superclasses_length \
230    >= classname##_SUPERCLASSES_LENGTH \
231    && ((const struct rootclassname##_representation_header *)(const struct any_##rootclassname##_representation *)(obj))->vtable->superclasses \
232       [((const struct rootclassname##_representation_header *)(const struct any_##rootclassname##_representation *)(obj))->vtable->superclasses_length \
233        - classname##_SUPERCLASSES_LENGTH] \
234       == & classname##_typeinfo)
235 /* This instance test consists of two comparisons.  One could even optimize
236    this to a single comparison, by limiting the inheritance depth to a fixed
237    limit, for example, say, depth <= 10.  The superclasses list would then
238    need to be stored in reverse order, from the root down to the class itself,
239    and be filled up with NULLs so that the array has length 10.  The instance
240    test would look like this:
241      #define IS_INSTANCE(obj,rootclassname,classname) \
242        (((const struct rootclassname##_representation_header *)(const struct any_##rootclassname##_representation *)(obj))->vtable->superclasses \
243         [classname##_SUPERCLASSES_LENGTH - 1] \
244         == & classname##_typeinfo)
245    but the classname##_superclasses_length would no longer be available as a
246    simple sizeof expression.  */
247 
248 #endif /* _MOO_H */
249