C objects consist of a header file and an implementation file. The header file defines how the object looks from the outside and how it can be used by a user. The implementation determines how this functionality is provided. It is mandatory that none of this implementation details is visible from the outside. Here is an example of a C object representing a car:
car.h
#ifndef CAR_H_
#define CAR_H_
#include <stdio.h>
typedef struct CarImpl* Car;
Car car_create();
void car_destroy(Car self);
void car_print(Car self, FILE* out);
void car_accelerate(Car self);
float car_getSpeed(Car self);
#endif /*CAR_H_*/
car.c
#include <stdlib.h>
#include "car.h"
typedef struct CarImpl {
float speed;
} CarImpl;
void car_print(Car self, FILE* out) {
fprintf(out, "Car speeds at %f km/h", self->speed);
}
void car_accelerate(Car self) {
self->speed += 100;
}
float car_getSpeed(Car self) {
return self->speed;
}
void car_destroy(Array self) {
free(self);
}
Car car_create() {
Car self = (Car)malloc(sizeof(CarImpl));
self->speed = 0.0f;
return self;
}
As you can see, each object needs at least a create and a destroy method.
The create method returns a pointer to the object. This pointer does not
reveal any details of the object. Therefore any access to the object goes
through additional methods which take the object pointer as a first parameter.
This is an important aspect of object oriented programming. Do not expose any
internals of an object. Never. Ever.
Properties are always private. Methods can be public or private. The methods
in the car example are public. If you like to define a private car method,
just define it as static in "car.c" and do not publish it in "car.h"
After making a car object, we can use the car somewhere else,
for example in "main.c":
main.c
#include "car.h"
int main(){
Car car = car_create();
car_accelerate(car);
car_print(car, stdout);
car_destroy(car);
return 0;
}
Here is another example of a C object. It is a boat. It also consists of two files, boat.h and boat.c .
boat.h
#ifndef BOAT_H_
#define BOAT_H_
#include <stdio.h>
typedef struct BoatImpl* Boat;
Boat boat_create();
void boat_destroy(Boat self);
void boat_print(Boat self, FILE* out);
void boat_accelerate(Boat self);
float boat_getSpeed(Boat self);
#endif /*BOAT_H_*/
boat.c
#include <stdlib.h>
#include "boat.h"
typedef struct BoatImpl {
float speed;
} BoatImpl;
void boat_print(Boat self, FILE* out) {
fprintf(out, "Boat speeds at %.0f km/h\n", self->speed);
}
void boat_accelerate(Boat self) {
self->speed += 10;
}
float boat_getSpeed(Boat self) {
return self->speed;
}
void boat_destroy(Boat self) {
free(self);
}
Boat boat_create() {
Boat self = (Boat)malloc(sizeof(BoatImpl));
self->speed = 0.0f;
return self;
}