Skip to content

Instantly share code, notes, and snippets.

@cwchentw cwchentw/employee.c
Created May 5, 2018

Embed
What would you like to do?
Polymorphism with Function Pointer in C.
#include <stdlib.h>
#include <assert.h>
#include "person.h"
#include "employee.h"
#include "iperson.h"
// Private helper function declaration.
static void check_salary(double salary);
static char* _name(void *self);
static void _set_name(void *self, char *name);
static unsigned int _age(void *self);
static void _set_age(void *self, unsigned int age);
struct employee {
Person* super;
char *company;
double salary;
};
Employee* employee_new(
char *name, unsigned int age, char *company, double salary)
{
check_salary(salary >= 0.0);
// Create parent object.
Person *super = person_new(name, age);
// Create child object.
Employee *ee = malloc(sizeof(Employee));
ee->super = super;
ee->company = company;
ee->salary = salary;
return ee;
}
char* employee_name(Employee *self)
{
return person_name(self->super);
}
void employee_set_name(Employee *self, char *name)
{
person_set_name(self->super, name);
}
unsigned int employee_age(Employee *self)
{
return person_age(self->super);
}
void employee_set_age(Employee *self, unsigned int age)
{
person_set_age(self->super, age);
}
char* employee_company(Employee *self)
{
return self->company;
}
void employee_set_company(Employee *self, char *company)
{
self->company = company;
}
double employee_salary(Employee *self)
{
return self->salary;
}
void employee_set_salary(Employee *self, double salary)
{
check_salary(salary);
self->salary = salary;
}
void employee_free(void *self)
{
if (self) {
free(self);
}
}
IPerson* employee_to_iperson(Employee *self)
{
IPerson *ip = malloc(sizeof(IPerson));
ip->name = _name;
ip->set_name = _set_name;
ip->age = _age;
ip->set_age = _set_age;
return ip;
}
static void check_salary(double salary)
{
assert(salary >= 0.0);
}
static char* _name(void *self)
{
return employee_name((Employee *) self);
}
static void _set_name(void *self, char *name)
{
employee_set_name((Employee *) self, name);
}
static unsigned int _age(void *self)
{
return employee_age((Employee *) self);
}
static void _set_age(void *self, unsigned int age)
{
employee_set_age((Employee *) self, age);
}
#ifndef EMPLOYEE_H
#define EMPLOYEE_H
#include "iperson.h"
typedef struct employee Employee;
Employee* employee_new(
char *name, unsigned int age, char *company, double salary);
char* employee_name(Employee *self);
void employee_set_name(Employee *self, char *name);
unsigned int employee_age(Employee *self);
void employee_set_age(Employee *self, unsigned int age);
char* employee_company(Employee *self);
void employee_set_company(Employee *self, char *company);
double employee_salary(Employee *self);
void employee_set_salary(Employee *self, double salary);
void employee_free(void *self);
IPerson* employee_to_iperson(Employee *self);
#endif // EMPLOYEE_H
#include <stdlib.h>
#include "iperson.h"
void iperson_free(void *self)
{
if (self) {
free(self);
}
}
#ifndef IPERSON_H
#define IPERSON_H
typedef struct iperson {
char* (*name) (void *self);
void (*set_name) (void *self, char *name);
unsigned int (*age) (void *self);
void (*set_age) (void *self, unsigned int age);
} IPerson;
void iperson_free(void *self);
#endif // IPERSON_H
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include "person.h"
#include "employee.h"
#include "iperson.h"
int main()
{
Person *p = person_new("Michael", 37);
IPerson *ipp = person_to_iperson(p);
Employee *ee = employee_new("Tommy", 28, "Google", 1000);
IPerson *ipee = employee_to_iperson(ee);
IPerson *ips[] = {ipp, ipee};
void *objs[] = {(void *) p, (void *) ee};
// Polymorphic calls.
for (int i = 0; i < 2; i++) {
printf("Name: %s\n", ips[i]->name(objs[i]));
printf("Age: %d\n", ips[i]->age(objs[i]));
}
// Mutate p.
ipp->set_name(p, "Mike");
ipp->set_age(p, 39);
// Mutate ee.
ipee->set_name(ee, "Tom");
ipee->set_age(ee, 30);
// Mutate ee with non-polymorphic call here.
employee_set_company(ee, "Microsoft");
employee_set_salary(ee, 1200);
printf("\n"); // Separator.
// Polymorphic calls again.
for (int i = 0; i < 2; i++) {
printf("Name: %s\n", ips[i]->name(objs[i]));
printf("Age: %d\n", ips[i]->age(objs[i]));
}
iperson_free(ipp);
iperson_free(ipee);
person_free(p);
employee_free(ee);
return EXIT_SUCCESS;
}
#include <stdlib.h>
#include "person.h"
static char* _name(void *self);
static void _set_name(void *self, char *name);
static unsigned int _age(void *self);
static void _set_age(void *self, unsigned int age);
struct person {
char *name;
unsigned int age;
};
Person* person_new(char *name, unsigned int age)
{
Person* p = malloc(sizeof(Person));
p->name = name;
p->age = age;
return p;
}
char* person_name(Person *self)
{
return self->name;
}
void person_set_name(Person *self, char* name)
{
self->name = name;
}
unsigned int person_age(Person *self)
{
return self->age;
}
void person_set_age(Person *self, unsigned int age)
{
self->age = age;
}
void person_free(void *self)
{
if (self) {
free(self);
}
}
IPerson* person_to_iperson(Person* self)
{
IPerson* ip = malloc(sizeof(IPerson));
ip->name = _name;
ip->set_name = _set_name;
ip->age = _age;
ip->set_age = _set_age;
return ip;
}
static char* _name(void *self)
{
return person_name((Person *) self);
}
static void _set_name(void *self, char *name)
{
person_set_name((Person *) self, name);
}
static unsigned int _age(void *self)
{
return person_age((Person *) self);
}
static void _set_age(void *self, unsigned int age)
{
person_set_age((Person *) self, age);
}
#ifndef PERSON_H
#define PERSON_H
#include "iperson.h"
typedef struct person Person;
Person* person_new(char *name, unsigned int age);
char* person_name(Person *self);
void person_set_name(Person *self, char *name);
unsigned int person_age(Person *self);
void person_set_age(Person *self, unsigned int age);
void person_free(void *self);
IPerson* person_to_iperson(Person* self);
#endif // PERSON_H
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.