Home > Back-end >  Create constructor in C
Create constructor in C

Time:08-20

I know C doesn't support OOP. I don't mean to seriously with using 4 pillar of OOP like Abstraction, Polymorphism, Encapsulation, Inheritence. But I'm trying to imitating OOP in C, more correctly, just creating a blueprint with struct as replacement of class where higher level program language usually use class keyword.

In this example case, I'm trying to create Animal blueprint where dog will be an instance of Animal.

Here is main.c:

#include "animal.h"

int main(void) {
  Animal dog; // Creating a dog instance from animal blueprint...
  dog.construct = Animal_construct; // Can I make private this line?
  dog.construct(&dog, "Doge", 8); //Constructing dog... 

  // Main Code
  dog.move(&dog, "walking"); // Moving a dog...
  printf("%s weight property is %u kilograms.\n", dog.name, dog.weigth);
  printf("%s name has %u characters.\n", dog.name, dog.get_name_length(&dog));

  return 0;
}

And this is the output:

Doge is moving (walking)...
Doge weight property is 8 kilograms.
Getting Doge name length...
Doge name has 4 characters.

The output is fine, no error.

And this is animal.h:

#ifndef ANIMAL_H
#define ANIMAL_H
#include <stdio.h>
#include <string.h>

typedef struct Animal Animal;
void Animal_construct(Animal *self, char *name, unsigned int weigth);

struct Animal {
  // Constructor
  void (*construct)(Animal *, name, weigth);

  // Properties
  char name[50];
  unsigned int weigth;

  // Methods
  void (*move)(Animal *, moveType);
  unsigned int (*get_name_length)(Animal *);
};

#endif

And this is animal.c:

#include "animal.h"

static void Animal_move(Animal *self, char *moveType) {
  printf("%s is moving (%s)...\n", self->name, moveType);
}

static unsigned int Animal_get_name_length(Animal *self) {
  printf("Getting %s name length...\n", self->name);
  return strlen(self->name);
}

void Animal_construct(Animal *self, char *name, unsigned int weigth) {
  strcpy(self->name, name);
  self->weigth = weigth;
  self->move = Animal_move;
  self->get_name_length = Animal_get_name_length;
}

The problem, if you see in main.c there's a line:

dog.construct = Animal_construct; // Can I make private this line?

So, can I just construct dog with single line statement without assigning Animal_construct right after dog has been instanced?

CodePudding user response:

You could create an Animal instance containing the default values and then use that to initialize your other instances.

Example:

animal.h

typedef struct Animal Animal;
struct Animal {
   // ...
};

extern const Animal animal;

animal.c

const Animal animal = {.construct = Animal_construct};

Then, in main.c

int main(void) {
  Animal dog = animal; // Creating a dog instance from `animal`
  dog.construct(&dog, "Doge", 8); //Constructing dog... 
  // ...
}

CodePudding user response:

I don't mean to seriously with using 4 pillar of OOP like Abstraction, Polymorphism, Encapsulation, Inheritence

Inheritance and polymorphism is kind of the same pillar, but you can get all of these in C, though it is somewhat cumbersome. Notably, constructors and RAII etc are not OO features, however they are handy features to have when implementing OO.

Check this out, as it answers the question: How to do private encapsulation in C? The part of that post regarding member functions explains some problems in your example too:

Note that in this example, member functions are declared in the header rather than as function pointers in a public part of the struct. Some like to use function pointers to emulate C -like member syntax like obj.member() (see for example Schreiner - Object-oriented Programming in ANSI-C, a book which I don't really recommend), but I think that's a rather pointless feature.

In C, there are no automatic constructor/destructor calls, no RAII, no this pointers. Meaning you have to pass along a reference to the object anyway.

So rather than writing foo.bar(&foo, stuff) you might as well write bar(&foo, stuff).

  • Related