{"id":565,"date":"2017-04-27T21:33:38","date_gmt":"2017-04-27T20:33:38","guid":{"rendered":"http:\/\/www.45rpmsoftware.com\/wordpress\/?p=565"},"modified":"2017-09-27T14:53:06","modified_gmt":"2017-09-27T13:53:06","slug":"object-oriented-c-objects","status":"publish","type":"post","link":"https:\/\/www.45rpmsoftware.com\/blog\/?p=565","title":{"rendered":"Object Oriented C &#8211; Objects"},"content":{"rendered":"<p>Bear with me a while.\u00a0I am going to stand of the shoulders of my favourite giants (Kernighan and Ritchie, since you ask) and address an oft-made point of criticism which is levelled against my code.<\/p>\n<p>The criticism? Namely that my C++ code looks suspiciously like C. There&#8217;s a good reason for this &#8211; I like C, and I&#8217;m not so keen on C++. C++ is (in my view, and with apologies to its many fans) a bad way of making C object oriented &#8211; as evidenced by the need, on occasion, to drop into plain old C in order to avoid name mangling. Objective C is object oriented C done right &#8211; but that&#8217;s a topic for another day. In the mean time, I want to address my critics by making C look like C++ &#8211; and writing an OOP program in C.<!--more--><\/p>\n<p>First of all though, and because there are a surprising number of people in IT who don&#8217;t know, what do we mean by OOP (Object Oriented Programming)?<\/p>\n<p>OOP (as opposed to Procedural Programming, from which it inherits) is a style of programming which revolves around the following concepts:<\/p>\n<h2>Objects<\/h2>\n<p>An object is an instance of a class. Objects might be something that the user can experience (a button on the screen, a window, or an alien spaceship for example), or they might be something invisible (but no less important) such as the means to load data from a file or open a network connection.<\/p>\n<p>Classes contain the code and data required for the object to run &#8211; each object is an instance of a\u00a0class.<\/p>\n<h2>Inheritance<\/h2>\n<p>Inheritance is a means of ensuring that code from existing classes can be reused. In addition, it permits existing classes to be extended without tampering with the actual class source code.<\/p>\n<p>For example, imagine two classes &#8216;Male&#8217; and &#8216;Female&#8217; which are used to instantiate (create) complete men and women. If it weren&#8217;t for inheritance there&#8217;d be an awful lot of code duplication &#8211; it would be necessary to have two sets of lung code, two sets of brain code, two sets of heart code.<\/p>\n<p>It&#8217;d be a maintainability disaster! Thankfully, we can write our &#8216;Male&#8217; and &#8216;Female&#8217; classes so that they inherit from a third class &#8216;Human&#8217;. &#8216;Human&#8217; contains all the common code, and the &#8216;Male&#8217; and &#8216;Female&#8217; classes only need to cover functions for the primary and secondary sexual characteristics. Much simpler.<\/p>\n<h2>Encapsulation<\/h2>\n<p>Encapsulation is a means of preventing access to internal object data, ensuring that the data can only be accessed and modified via methods. That&#8217;s not to say the internal object data can never be manipulated directly &#8211; but one has the option to decide how best the data should be accessed. In explicitly OOP languages this is often achieved through the use of the &#8216;private&#8217;, &#8216;public&#8217; and &#8216;protected&#8217; keywords.<\/p>\n<h2>Polymorphism<\/h2>\n<p>Polymorphism is an partner concept to Inheritance. It allows the subclasses to implement their own versions of a common function. In the case of our &#8216;Male&#8217; and &#8216;Female&#8217; classes, both will be able to speak &#8211; but the characteristics of speech will be different. &#8216;Human&#8217; will also have a &#8216;speak&#8217; function to fall back on. For the sake of argument, lets say that the &#8216;Human&#8217; speech function is defined to be flat, the &#8216;Female&#8217; speech function is defined to pitched high and the &#8216;Male&#8217; function pitched deep. If we call the speech function on an object instantiated from the &#8216;Male&#8217; class, it will sound deep (the speech function in the &#8216;Male&#8217; class has overridden the speech function in the &#8216;Human&#8217; superclass).<\/p>\n<p>That said, I&#8217;m not going to discuss all the terms that will be used in this post. You&#8217;ll need to have some programming chops before going any further (so if you don&#8217;t know your pointer from your struct you might want to stop now, and invest in a copy of The C Programming Language by Brian Kernighan and Dennis\u00a0Ritchie (<a href=\"https:\/\/www.amazon.co.uk\/C-Programming-Language-2nd\/dp\/0131103628\">The C Programming Language (2nd Edition)<\/a>)<\/p>\n<p>So without more ado, I&#8217;ll deal with the object part of Object Oriented &#8211; by creating an object in C. C gets us most of the way with a struct. A class (the code and data for the object) is just a struct with added code &#8211; so how hard can this be?<\/p>\n<pre>#include &lt;stdio.h&gt;\r\n#include &lt;stdlib.h&gt;\r\n \r\ntypedef struct cClass class;\r\n \r\nstruct cClass { \/\/ this struct is the container for our class\r\n int data; \/\/ it has data\u2026\r\n void (*setValue) (class*,int); \/\/ \u2026and a function. A pointer to a function\r\n \/\/ in this case.\r\n};\r\n \r\nvoid cClassSetValue(class* self, int value) {\r\n self-&gt;data = value;\r\n}\r\n \r\nclass* cClassCreate() {\r\n class* self = malloc((sizeof(class))); \/\/ gonna need some memory.\r\n self-&gt;data = 0; \/\/ \u2026and initialise the data\r\n self-&gt;setValue = cClassSetValue; \/\/ \u2026and pointers to our class functions\r\n return self; \/\/ and now we can return our 'self'\r\n}\r\n \r\nint main(int argc, const char* argv[]) {\r\n class* foo = cClassCreate(); \/\/ instantiate one object\r\n class* bar = cClassCreate(); \/\/ instantiate a second object\r\n foo-&gt;setValue(foo,1); \/\/ give it a value\r\n bar-&gt;setValue(bar,2);\r\n printf(\"%d\\n\", foo-&gt;data); \/\/ output the value\r\n printf(\"%d\\n\", bar-&gt;data);\r\n free(foo); \/\/ and release its memory now we're done\r\n free(bar);\r\n return 0;\r\n}<\/pre>\n<p>Okay, I concede. It&#8217;s not the most elegant code &#8211; but it&#8217;s not too bad, and we&#8217;ve clearly got a class here and instantiated two objects (foo and bar). Incidentally, I&#8217;m told that this is how C++ started &#8211; originally C++ was nothing more than a bunch of preprocessor directives that converted Stroustrup&#8217;s C++ bits and pieces into Kernighan and Ritchie&#8217;s canonical C.<\/p>\n<p>All that I&#8217;ve done is create a plain old C struct with some data in it (an int in this case), and a function pointer (for the executable code). To some eyes, it might not be elegant &#8211; but it contains data and code &#8211; so it is, demonstrably, a class. Anything we create with it is therefore an object.<\/p>\n<p>Extending this a little further, one of the criticisms that often gets levelled at C is that its string handling is pretty rudimentary &#8211; which is amusing because, in fact, C can&#8217;t handle strings at all (or, at least, not without a fairly extensive library of functions). Using these OO techniques, we can hugely improve C&#8217;s string handling abilities. This is a start &#8211; the main point being to demonstrate that we can grow (and shrink) the storage for our C class. Your challenge is to extend this class to add all the other functions which might be useful. A little error handling might be useful too &#8211; but this is about how to create objects in C, not how to handle errors!<\/p>\n<p>When a string is embiggened, more memory is automatically allocated by this class. When a string is debigulated, the extra, unneeded, memory is automatically freed.<\/p>\n<pre>#include &lt;stdio.h&gt;\r\n#include &lt;stdlib.h&gt;\r\n#include &lt;string.h&gt;\r\n \r\ntypedef struct cStringClass stringClass;\r\n \r\nstruct cStringClass {\r\n char *s;\r\n size_t size;\r\n void (*setString) (stringClass*,char*); \/\/ one function\u2026\r\n size_t (*stringSize) (stringClass*); \/\/ \u2026and a second function\r\n};\r\n \r\nvoid cStringClassSetString(stringClass *self, char* str) {\r\n char *buf;\r\n self-&gt;size = strlen(str);\r\n \r\n buf = realloc(self-&gt;s, self-&gt;size + 1); \/\/ reallocate enough memory for\r\n \/\/ the new string\r\n if (buf) { \/\/ if successful, update self\r\n self-&gt;s = buf;\r\n strncpy (self-&gt;s, str, self-&gt;size + 1); \/\/ and copy str into our s\r\n }\r\n}\r\n \r\nsize_t cStringClassStringSize(stringClass* self) {\r\n return self-&gt;size; \/\/ Not using this function. It's just\r\n \/\/ here to show that your C class\r\n \/\/ doesn't have to be monofunctional!\r\n}\r\n \r\nstringClass* cStringClassCreate() {\r\n stringClass* self = malloc((sizeof(stringClass)));\r\n \r\n if (self != NULL) {\r\n self-&gt;stringSize = cStringClassStringSize;\r\n self-&gt;setString = cStringClassSetString;\r\n self-&gt;s = NULL;\r\n self-&gt;size = 0;\r\n }\r\n return self;\r\n}\r\n \r\nint main(int argc, const char* argv[]) {\r\n stringClass* foo = cStringClassCreate();\r\n stringClass* bar = cStringClassCreate();\r\n foo-&gt;setString(foo,\"Hello\");\r\n bar-&gt;setString(bar,\"World\");\r\n printf(\"%s\\n\", foo-&gt;s);\r\n printf(\"%s\\n\", bar-&gt;s);\r\n foo-&gt;setString(foo,\"Watchamacallit\"); \/\/ Allocate more memory on the heap\r\n bar-&gt;setString(bar,\"!\"); \/\/ free memory on the heap\r\n printf(\"%s\\n\", foo-&gt;s);\r\n printf(\"%s\\n\", bar-&gt;s);\r\n free(foo);\r\n free(bar);\r\n return 0;\r\n}\r\n<\/pre>\n<p>In the loosest sense, this is Object Oriented programming. Sure, we&#8217;ve missed a few concepts &#8211; but the classes and objects are present, so I&#8217;m happy. And, of course, if we were doing this in anger then each class would be in its own file.<\/p>\n<p>If you liked this then please comment and &#8216;Like&#8217; this. With enough encouragement I&#8217;ll set myself the far bigger challenge of Inheritance, Polymorphism and Encapsulation.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Bear with me a while.\u00a0I am going to stand of the shoulders of my favourite giants (Kernighan and Ritchie, since you ask) and address an oft-made point of criticism which is levelled against my code. The criticism? Namely that my C++ code looks suspiciously like C. There&#8217;s a good reason for this &#8211; I like &hellip; <\/p>\n<p class=\"link-more\"><a href=\"https:\/\/www.45rpmsoftware.com\/blog\/?p=565\" class=\"more-link\">Continue reading<span class=\"screen-reader-text\"> &#8220;Object Oriented C &#8211; Objects&#8221;<\/span><\/a><\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":[],"categories":[15,18,28,5],"tags":[],"_links":{"self":[{"href":"https:\/\/www.45rpmsoftware.com\/blog\/index.php?rest_route=\/wp\/v2\/posts\/565"}],"collection":[{"href":"https:\/\/www.45rpmsoftware.com\/blog\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.45rpmsoftware.com\/blog\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.45rpmsoftware.com\/blog\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.45rpmsoftware.com\/blog\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=565"}],"version-history":[{"count":0,"href":"https:\/\/www.45rpmsoftware.com\/blog\/index.php?rest_route=\/wp\/v2\/posts\/565\/revisions"}],"wp:attachment":[{"href":"https:\/\/www.45rpmsoftware.com\/blog\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=565"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.45rpmsoftware.com\/blog\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=565"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.45rpmsoftware.com\/blog\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=565"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}