OBJECT-ORIENTED PROGRAMMING IN C CSCI 5448 Pritha Srivastava Fall 2012
Introduction Goal : To discover how ANSI – C can be used to write object- oriented code To revisit the basic concepts in OO like Information Hiding, Polymorphism, Inheritance etc… Pre-requisites – A good knowledge of pointers, structures and function pointers
Table of Contents Information Hiding Dynamic Linkage & Polymorphism Visibility & Access Functions Inheritance Multiple Inheritance Conclusion
Information Hiding Data types - a set of values and operations to work on them OO design paradigm states – conceal internal representation of data, expose only operations that can be used to manipulate them Representation of data should be known only to implementer, not to user – the answer is Abstract Data Types
Information Hiding Make a header file only available to user, containing a descriptor pointer (which represents the user-defined data type) functions which are operations that can be performed on the data type Functions accept and return generic ( void ) pointers which aid in hiding the implementation details
Information Hiding Set.h Example: Set of elements Type Descriptor operations – add, find extern const void * Set; and drop . Define a header file void* add(void *set, const void Set.h (exposed to user) *element); Appropriate void* find(const void *set, const Abstractions – Header void *element); file name, function name void* drop(void *set, const void reveal their purpose *element); int contains(const void *set, const Return type - void* helps void *element); in hiding implementation details Main.c - Usage Set.c
Information Hiding Set.c – Contains void* add (void *_set, void *_element) { implementation details of struct Set *set = _set; Set data type (Not struct Object *element = _element; exposed to user) if ( !element-> in) The pointer Set (in Set.h) is { element->in = set; passed as an argument to } add, find etc. else Set.c assert(element->in == set); struct Set { unsigned count; }; ++set->count; ++element->count; static const size_t _Set = sizeof(struct Set); return element; } const void * Set = & _Set; find(), drop(), contains() etc … Externed in Set.h Main.c - Usage Set.h
Information Hiding Set is a pointer, NOT a New.h Takes in pointer ‘Set’ data type Need to define a void* new (const void* type, …); mechanism using which void delete (void *item); Arguments variables of type Set can with which to be declared initialize the Define a header file – variable New.h new – creates variable conforming to descriptor Set delete – recycles variable created Main.c - Usage New.c
Information Hiding New.c – Contains void* new (const void * type, ...) implementations for { new() and delete() const size_t size = * (const size_t *) type; void * p = calloc(1, size); assert(p); return p; } d elete() … Main.c - Usage New.h
Information Hiding Need another data Object.h Type Descriptor type to represent an Object that will be extern const void *Object; added to a Set Define a header file Compares variables of type ‘Object’ – Object.h int differ(const void *a, const void *b); Object.c Main.c - Usage
Information Hiding Object.c – struct Object { unsigned count; struct Set * in; }; Contains implementation static const size_t _Object = sizeof(struct details of Object Object); data type (Not const void * Object = & _Object; exposed to user) Externed in Object.h int differ (const void * a, const void * b) { return a != b; } Object.h Main.c - Usage
Information Hiding Application to demonstrate void *b = add(s, new(Object)); the usage of Set.h, void *c = new(Object); Object.h & New.h Pointer ‘Object’ externed in Object.h #include <stdio.h> #include “New.h” if(contains(s, a) && contains(s,b)) Only header files #include “Set.h” puts(“OK”); given to user #include “Object.h” delete(drop(s, b)); int main() delete(drop(s, a)); Pointer ‘Set’ externed in Set.h { } void *s = new (Set); void *a = add(s, new(Object); Output: OK New.c Set.h Set.c Object.h Object.c New.h
Dynamic Linkage & Polymorphism A generic function should be able to invoke type- specific functions using the pointer to the object Demonstrate with an example how function pointers can be used to achieve this Introduce how constructors , destructors and other such generic functions can be defined and invoked dynamically
Dynamic Linkage & Polymorphism Problem: Implement a String data type to be included/ added to a Set Requires a dynamic buffer to hold data Possible Solution: new() – can include memory allocation; but will have a chain of ‘if’ statements to support memory allocations and initializations specific to each data-type Similar problems with delete() for reclamation of memory allocated
Dynamic Linkage & Polymorphism Elegant Solution: Each object must be responsible for initializing and deleting its own resources (constructor & destructor) new() – responsible for allocating memory for struct String & constructor responsible for allocating memory for the text buffer within struct String and other type-specific initializations delete() – responsible for freeing up memory allocated for struct String & destructor responsible for freeing up memory allocated for text buffer within struct String
Dynamic Linkage & Polymorphism struct Class { How to Locate the /* Size of the object */ constructor & destructor size_t size; within new() & delete() ? /* Constructor */ Define a table of function void * (* ctor) (void * self, va_list * app); pointers which can be /* Destructor */ common for each data- void * (* dtor) (void * self); type /* Makes a copy of the object self */ Associate this table with void * (* clone) (const void * self); the data-type itself /* Compares two objects */ Example of table – Struct int (* differ) (const void * self, const void * b); Class };
Dynamic Linkage & Polymorphism struct Class has to be struct String { made a part of the const void * class; /* must be first */ data - type char * text; pointer to struct Class is }; there in the data - type struct Set { String and Set const void * class; /* must be first */ ... };
Dynamic Linkage & Polymorphism struct Class pointer at the void * new (const void * _class, ...) Allocate beginning of each Object is memory for p { of size important, so that it can be used const struct Class * class = _class; given in _class to locate the dynamically linked void * p = calloc(1, class — > size); function (constructor & destructor) * (const struct Class **) p = class; as shown if (class — > ctor) new() & delete() can be used to Assign class at { the beginning allocate memory for any data- va_list ap; of the new type variable p va_start(ap, _class); void delete (void * self) p = class — > ctor(p, & ap); { va_end(ap); Locate and const struct Class ** cp = self; invoke the } if (self && * cp && (* cp) — > dtor) dynamically return p; linked self = (* cp) — > dtor(self); constructor } free(self); }
Dynamic Linkage & Polymorphism int differ (const void * self, const void * b) size_t sizeOf (const void * self) { { const struct Class * const * cp = self; const struct Class * const * cp = self; assert(self && * cp && (* cp) — >differ); assert(self && * cp); Dynamica Variable which return (* cp) — > differ(self, b); return (* cp) — > size; lly linked stores size in } function } struct Class Polymorphism : differ() is a Dynamic Linkage/ Late Binding : the function that does the actual generic function which takes in work is called only during execution arguments of any type (void Static Linkage: Demonstrated by *), and invokes the sizeOf(). It can take in any object as appropriate dynamically argument and return its size which is linked function based on the stored as a variable in the pointer type of the object of type struct Class
Dynamic Linkage & Polymorphism Define a header file String.h String.h which defines the abstract data extern const void * String; type- String:
Dynamic Linkage & Polymorphism Define another header String.r file String.r which is the representation file for struct String { String data-type /* must be first */ const void * class; char * text; };
Recommend
More recommend