File tree 9 files changed +230
-0
lines changed
9 files changed +230
-0
lines changed Original file line number Diff line number Diff line change
1
+ test
Original file line number Diff line number Diff line change
1
+ build :
2
+ gcc main.c animal.c dog.c -o test
3
+
4
+ memcheck :
5
+ valgrind ./test
6
+
7
+ clean :
8
+ rm test
Original file line number Diff line number Diff line change
1
+ # Object Oriented Test
2
+
3
+ Since there are so many ways to make object oriented C code, I decided to try
4
+ out a few different methods and develop my favorite one. This is the result of
5
+ that experiment. It's a simple example with a few classes and a simple class
6
+ structure, with a parent Animal class and a child Dog class. The Animal class
7
+ has a virtual method that the Dog class overwrites. It's a pretty simple method
8
+ to do some really cool things, IMO. Other ways seemed to involve a lot more
9
+ boilerplate code and didn't really look as pretty as I would have liked.
10
+
11
+ ## Build it
12
+
13
+ ```
14
+ make
15
+ ```
16
+
17
+ ## Try it
18
+
19
+ ```
20
+ ./test
21
+ ```
22
+
23
+ ## Clean it
24
+
25
+ ```
26
+ make clean
27
+ ```
28
+
29
+ ## Check it for memory leaks (requires valgrind)
30
+
31
+ ```
32
+ make memcheck
33
+ ```
Original file line number Diff line number Diff line change
1
+ #include "animal.h"
2
+
3
+ int animal_new (animal_t * self , const char * type ) {
4
+ if (type == NULL ) {
5
+ return ERROR_VAL ;
6
+ }
7
+
8
+ self -> type = malloc (strlen (type )+ 1 );
9
+ strcpy (self -> type , type );
10
+
11
+ return SUCCESS_VAL ;
12
+ }
13
+
14
+ int animal_delete (animal_t * self ) {
15
+ if (self -> type != NULL ) {
16
+ free (self -> type );
17
+ self -> type = NULL ;
18
+ }
19
+
20
+ return SUCCESS_VAL ;
21
+ }
22
+
23
+ void animal_speak (animal_t * self ) {
24
+ if (self -> vtable .speak ) {
25
+ return self -> vtable .speak (self );
26
+ }
27
+
28
+ printf ("This %s cannot speak!" , self -> type );
29
+ }
Original file line number Diff line number Diff line change
1
+ #ifndef ANIMAL_H
2
+ #define ANIMAL_H
3
+
4
+ #include <stdlib.h>
5
+ #include <stdio.h>
6
+ #include <string.h>
7
+
8
+ #include "error.h"
9
+
10
+ typedef struct {
11
+ struct {
12
+ void (* speak )(void * self );
13
+ } vtable ;
14
+
15
+ char * type ;
16
+ } animal_t ;
17
+
18
+ int animal_new (animal_t * self , const char * type );
19
+
20
+ int animal_delete (animal_t * self );
21
+
22
+ void animal_speak (animal_t * self );
23
+
24
+ // Create a nice structure to expose them in :D
25
+ static const struct {
26
+ int (* new )(animal_t * , const char * );
27
+ int (* delete )(animal_t * );
28
+
29
+ void (* speak )(animal_t * );
30
+ } Animal = {
31
+ .new = & animal_new ,
32
+ .delete = & animal_delete ,
33
+ .speak = & animal_speak ,
34
+ };
35
+
36
+ #endif // ANIMAL_H
Original file line number Diff line number Diff line change
1
+ #include "dog.h"
2
+
3
+ void dog_speak (void * _self ) {
4
+ dog_t * self = _self ;
5
+ printf ("'woof!' says the %s %s dog!\n" , self -> size , self -> furColor );
6
+ }
7
+
8
+ int dog_new (dog_t * self , const char * furColor , const char * size ) {
9
+ if (furColor == NULL || size == NULL ) {
10
+ return ERROR_VAL ;
11
+ }
12
+
13
+ Animal .new (& (self -> super ), "dog" );
14
+
15
+ self -> super .vtable .speak = & dog_speak ;
16
+
17
+ self -> furColor = malloc (strlen (furColor ) + 1 );
18
+ strcpy (self -> furColor , furColor );
19
+
20
+ self -> size = malloc (strlen (size ) + 1 );
21
+ strcpy (self -> size , size );
22
+
23
+ return SUCCESS_VAL ;
24
+ }
25
+
26
+ int dog_delete (dog_t * self ) {
27
+ Animal .delete (& self -> super );
28
+
29
+ if (self -> furColor != NULL ) {
30
+ free (self -> furColor );
31
+ self -> furColor = NULL ;
32
+ }
33
+ if (self -> size != NULL ) {
34
+ free (self -> size );
35
+ self -> size = NULL ;
36
+ }
37
+
38
+ return SUCCESS_VAL ;
39
+ }
40
+
41
+ const char * dog_getFurColor (dog_t * self ) {
42
+ return self -> furColor ;
43
+ }
44
+
45
+ const char * dog_getSize (dog_t * self ) {
46
+ return self -> size ;
47
+ }
Original file line number Diff line number Diff line change
1
+ #ifndef DOG_H
2
+ #define DOG_H
3
+
4
+ #include <stdlib.h>
5
+ #include <string.h>
6
+
7
+ #include "error.h"
8
+
9
+ // INHERITS FROM ANIMAL
10
+ #include "animal.h"
11
+
12
+ typedef struct {
13
+ animal_t super ;
14
+ char * furColor ;
15
+ char * size ;
16
+ } dog_t ;
17
+
18
+ // Creates a dog, takes fur color and size. Returns pointer to dog. This copies
19
+ // the strings.
20
+ int dog_new (dog_t * self , const char * furColor , const char * size );
21
+
22
+ // Deletes a dog. Takes pointer to dog created with dog_ctor D:
23
+ int dog_delete (dog_t * self );
24
+
25
+ // Gets the fur color passed to the constructor, takes pointer to dog created
26
+ // with dog_ctor.
27
+ const char * dog_getFurColor (dog_t * self );
28
+
29
+ // Gets the size passed to the constructor, takes pointer to dog created with
30
+ // dog_ctor.
31
+ const char * dog_getSize (dog_t * self );
32
+
33
+ // Create a nice structure to expose them in :D
34
+ static const struct {
35
+ int (* new )(dog_t * , const char * furColor , const char * size );
36
+ int (* delete )(dog_t * );
37
+
38
+ const char * (* getFurColor )(dog_t * );
39
+ const char * (* getSize )(dog_t * );
40
+ } Dog = {
41
+ .new = & dog_new ,
42
+ .delete = & dog_delete ,
43
+ .getFurColor = & dog_getFurColor ,
44
+ .getSize = & dog_getSize
45
+ };
46
+
47
+ #endif // DOG_H
Original file line number Diff line number Diff line change
1
+ #ifndef ERROR_H
2
+ #define ERROR_H
3
+
4
+ #define ERROR_VAL -1
5
+ #define SUCCESS_VAL 0
6
+ #define ERROR (err) { errno = (err); }
7
+
8
+ #endif // ERROR_H
Original file line number Diff line number Diff line change
1
+ #include <stdarg.h>
2
+ #include <stdlib.h>
3
+ #include <stdio.h>
4
+ #include <string.h>
5
+ #include <errno.h>
6
+
7
+ #include "dog.h"
8
+
9
+ int main (int argc , char * argv []) {
10
+ dog_t * dog = malloc (sizeof (dog_t ));
11
+ Dog .new (dog , "white" , "small" );
12
+
13
+ printf ("The %s dog has %s fur!\n" , Dog .getSize (dog ), Dog .getFurColor (dog ));
14
+
15
+ Animal .speak ((animal_t * )dog );
16
+
17
+ Dog .delete (dog );
18
+ free (dog );
19
+
20
+ return 0 ;
21
+ }
You can’t perform that action at this time.
0 commit comments