Portable Inheritance and Polymorphism in C, 12/97
Portable Inheritance and Polymorphism in C, 12/97
Portable Inheritance and Polymorphism in C, 12/97
- No tags were found...
You also want an ePaper? Increase the reach of your titles
YUMPU automatically turns print PDFs into web optimized ePapers that Google loves.
In spite of theunquestionedadvantages of OOlanguages, C stillrema<strong>in</strong>s the bestknown implementationlanguage.best known <strong>and</strong> widespread implementationlanguage. Many embedded systemstoday still simply do not offer anyother choice. Consequently, mostdevelopers still exclusively use proceduralprogramm<strong>in</strong>g techniques, <strong>and</strong>many are unaware that it’s quite easyto implement key OO concepts directly<strong>in</strong> C. Promot<strong>in</strong>g this awareness maybe important for at least two reasons.The first is leverag<strong>in</strong>g OO technology.Most OO designs can be implemented<strong>in</strong> C, but many developerswouldn’t consider them without theavailability of an OO language. Thisunnecessarily limits application of thetechnology.The second is smooth<strong>in</strong>g transitionfrom procedural to OO th<strong>in</strong>k<strong>in</strong>g.Migrat<strong>in</strong>g to OO technology canrequire quite a leap <strong>in</strong> your way ofth<strong>in</strong>k<strong>in</strong>g. Implement<strong>in</strong>g OO concepts<strong>in</strong> currently used <strong>and</strong> familiar languagesgives you an opportunity to getexposed to the new programm<strong>in</strong>g paradigmright away <strong>and</strong> without major<strong>in</strong>vestment.ENCAPSULATIONYou can achieve packag<strong>in</strong>g ofdata with functions <strong>in</strong> C bymak<strong>in</strong>g each class attribute(<strong>in</strong>stance variable) a field <strong>in</strong> the Cstruct. You implement class methodsas C functions that take as their firstargument the po<strong>in</strong>ter to the structure ofattributes (the this po<strong>in</strong>ter). You canfurther strengthen the associationbetween the attributes <strong>and</strong> methods bya consistent nam<strong>in</strong>g convention formethod names. The most popular conventionthat I adopt is to concatenatethe structure name (class name) withthe operation name. This alter<strong>in</strong>g offunction names is part of name decorat<strong>in</strong>g(also known as name mangl<strong>in</strong>g)<strong>and</strong> is performed implicitly by mostC++ compilers. Because name decorat<strong>in</strong>gelim<strong>in</strong>ates method name clashesbetween different classes, it effectivelypartitions the flat C function namespace<strong>in</strong>to separate namespaces nestedwith<strong>in</strong> classes.The next aspect I address by a cod<strong>in</strong>gconvention is access control. In C,you can only <strong>in</strong>dicate your <strong>in</strong>tentionfor the level of access permitted to aparticular attribute or a method.Convey<strong>in</strong>g this <strong>in</strong>tention through thename of an attribute or a method is betterthan just express<strong>in</strong>g it <strong>in</strong> the form ofa comment at the declaration po<strong>in</strong>t. Inthis way, un<strong>in</strong>tentional access to classmembers <strong>in</strong> any portion of the codewill be easier to detect. Most OOdesigns dist<strong>in</strong>guish the follow<strong>in</strong>g threelevels of protection:■■■private—accessible only from with<strong>in</strong>the classprotected—accessible only by theclass <strong>and</strong> its subclassespublic—available anywhere (default<strong>in</strong> C)I use a double underscore prefix(__foo) for private attributes. Note thatthere is usually no need to expose privatemethods (helper methods) <strong>in</strong> theclass declaration file (.H file). Rather,you should hide them completely <strong>in</strong>the implementation file (declare themstatic <strong>in</strong> the .C file). For protectedmembers I use a s<strong>in</strong>gle underscore(_foo, Str<strong>in</strong>g_Foo). I avoid us<strong>in</strong>g underscores<strong>in</strong> the public members at all(foo, Str<strong>in</strong>gFoo). So, with this convention,the presence of underscores <strong>in</strong> aname is a signal that access rightsshould be checked aga<strong>in</strong>st the contextof use. Because public members can beused without any constra<strong>in</strong>ts, theydon’t need any special adornment.Every class must provide at leastone constructor method for <strong>in</strong>itializationof its attribute structure.Constructor calls should be the onlymethod of <strong>in</strong>itialization. Otherwise, the<strong>in</strong>ternal structure of an object must beDECEMBER 19<strong>97</strong> EMBEDDED SYSTEMS PROGRAMMING 55
<strong>Portable</strong> <strong>Inheritance</strong> <strong>and</strong> <strong>Polymorphism</strong>exposed, thereby compromis<strong>in</strong>gencapsulation.Optionally, a class may provide adestructor, which is a method responsiblefor releas<strong>in</strong>g the resources allocateddur<strong>in</strong>g the lifetime of an object.Whereas there may be many ways of<strong>in</strong>stantat<strong>in</strong>g a class (different constructorstak<strong>in</strong>g different arguments), thereshould be only one way of destroy<strong>in</strong>gan object.Because of the special role of constructors<strong>and</strong> destructors, I aga<strong>in</strong>advise a consistent nam<strong>in</strong>g pattern. Iuse base names “Con” (FooCon1,FooCon2) <strong>and</strong> “Des” (FooDes) for constructors<strong>and</strong> destructors, respectively.I suggest that constructors return eitherthe po<strong>in</strong>ter to a properly <strong>in</strong>itializedattribute structure, or NULL if <strong>in</strong>itializationfails. The destructor should takeonly the this argument <strong>and</strong> shouldreturn void.Objects can be allocated statically,dynamically (on the heap), or automatically(on the stack). Because of C syntaxlimitations, you generally cannot<strong>in</strong>itialize objects through a constructorcall at the def<strong>in</strong>ition po<strong>in</strong>t. For staticobjects, you cannot call a constructorat all, because function calls aren’t permitted<strong>in</strong> a static <strong>in</strong>itializer. Automaticobjects must all be def<strong>in</strong>ed at thebeg<strong>in</strong>n<strong>in</strong>g of a block <strong>and</strong> at this po<strong>in</strong>t,you will generally not have enough <strong>in</strong>itialization<strong>in</strong>formation to call an appropriateconstructor. Therefore, you willoften have to divorce object allocationfrom <strong>in</strong>itialization. You should treatobjects as all other C variables, <strong>in</strong> thatyou never use them before <strong>in</strong>itialization.Typically, you’ll want to <strong>in</strong>itializeobjects as soon as the <strong>in</strong>itialization<strong>in</strong>formation becomes available.Some objects may require destruction,<strong>and</strong> call<strong>in</strong>g destructors for allobjects when they become obsolete orgo out of scope is a good programm<strong>in</strong>gpractice. Later, I’ll show that a virtualdestructor is available for all classes.INHERITANCE<strong>Inheritance</strong> is a mechanism bywhich new <strong>and</strong> more specializedclasses can be def<strong>in</strong>ed <strong>in</strong> terms ofexist<strong>in</strong>g classes. When a child class(subclass) <strong>in</strong>herits from a parent class(superclass), the subclass then <strong>in</strong>cludesthe def<strong>in</strong>itions of all the attributes <strong>and</strong>methods that the superclass def<strong>in</strong>es.Usually, the subclass extends thesuperclass by add<strong>in</strong>g its own attributes<strong>and</strong> methods. Objects that are <strong>in</strong>stancesof the subclass conta<strong>in</strong> all data def<strong>in</strong>edby the subclass <strong>and</strong> its parent classes,<strong>and</strong> they are able to perform all operationsdef<strong>in</strong>ed by this subclass <strong>and</strong> itsparents.This k<strong>in</strong>d of class relationship canbe implemented <strong>in</strong> C by embedd<strong>in</strong>g theparent class attribute structure as the56 EMBEDDED SYSTEMS PROGRAMMING DECEMBER 19<strong>97</strong>
<strong>Portable</strong> <strong>Inheritance</strong> <strong>and</strong> <strong>Polymorphism</strong>yourself that these modifications don’trequire any manual changes to subclasses.I also strongly recommend thatyou step through the code us<strong>in</strong>g adebugger.Encapsulation,<strong>in</strong>heritance, <strong>and</strong>polymorphism arenoth<strong>in</strong>g but designpatterns at the Clanguage level.WHAT’S TO LOSE?So what do you lose by us<strong>in</strong>g Crather than an OO language?Us<strong>in</strong>g the techniques I’ve presentedhere, you don’t have to sacrificemuch convenience <strong>and</strong> expressiveness,because you can fairly easily map mostimportant OO concepts to C. Youdon’t have to compromise much ma<strong>in</strong>ta<strong>in</strong>abilityeither, because you canautomate many tasks. The most importantfeature of this implementation isthat add<strong>in</strong>g new attributes <strong>and</strong> methods(<strong>in</strong>clud<strong>in</strong>g virtual functions <strong>and</strong> <strong>in</strong>terfaces)to the superclass doesn’t requireany manual changes to subclasses.The real issue is that C requires significantlyhigher programm<strong>in</strong>g discipl<strong>in</strong>e<strong>in</strong> object <strong>in</strong>itialization <strong>and</strong>cleanup than OO languages, especiallythose with garbage collection. But thisis a well known deficiency of C, whichisn’t to be repaired easily. (For example,C++ is still plagued by most ofthese problems.)Encapsulation, <strong>in</strong>heritance, <strong>and</strong>polymorphism are noth<strong>in</strong>g but designpatterns at the C language level(Gamma, 1995). As do all design patterns,they br<strong>in</strong>g a higher (OO) level ofabstraction by <strong>in</strong>troduc<strong>in</strong>g their specificnam<strong>in</strong>g conventions <strong>and</strong> idioms. Ifyou aren’t comfortable with my conventions,you should adopt your own.Most important is consistency, whichdramatically improves code readability<strong>and</strong> allows for quick identification ofthe patterns.If you start us<strong>in</strong>g these patterns, youwill probably notice that they completelychange your th<strong>in</strong>k<strong>in</strong>g <strong>and</strong> programm<strong>in</strong>gstyle <strong>in</strong> C. You’ll not onlyf<strong>in</strong>d your C code to be more similar toJava, you’ll f<strong>in</strong>d yourself more preparedfor Java.Miro Samek is a software eng<strong>in</strong>eer atGE Medical Systems, currently develop<strong>in</strong>greal-time, embedded software fordiagnostics x-ray equipment. He holdsa PhD <strong>in</strong> physics from JagiellonianUniversity <strong>in</strong> Cracow, Pol<strong>and</strong>. Mirohas previously worked on nuclearphysics experiments at GSI Darmstadt,Germany. He may be reached atmiroslaw.samek@med.ge.com.REFERENCES1. Gosl<strong>in</strong>g, James <strong>and</strong> HenryMcGilton, “The Java LanguageEnvironment: A White Paper,” SunMicrosystems, 1995.2. Rumbaugh, James, MichaelBlaha, William Premerlani, FrederickEddy, <strong>and</strong> William Loernsen. Object-Oriented Modell<strong>in</strong>g <strong>and</strong> Design.Englewood Cliffs, NJ: Prentice Hall,1991.3. Eckel, Bruce. Th<strong>in</strong>k<strong>in</strong>g <strong>in</strong> C++.Englewood Cliffs, NJ: Prentice Hall,1995.4. Gamma, Erich, Richard Helm,Ralph Johnson, <strong>and</strong> John Vlissides.Design Patterns: Elements of ReusableObject-Oriented Software. Read<strong>in</strong>g,MA: Addison-Wesley, 1995.5. Arnold, Ken <strong>and</strong> James Gosl<strong>in</strong>g.The Java Programm<strong>in</strong>g Language.Read<strong>in</strong>g, MA: Addison-Wesley, 1996.66 EMBEDDED SYSTEMS PROGRAMMING DECEMBER 19<strong>97</strong>