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