Encapsulating instance structure

Asked

Viewed 41 times

1

Given the following code, implement a small library that makes it possible.

#include <stdio.h>
#include "object.h"

int main() {
    obj_instance *oi1;
    obj_instance *oi2;
    
    object_init();
    
    oi1 = Object.New();
    oi2 = Object.New();

    Object.Set(oi1, 5);
    Object.Set(oi2, 3);
    
    printf("valor de oi1: %d\n", Object.Get(oi1));
    printf("valor de oi2: %d\n", Object.Get(oi2));

    printf("oi1 y oi2 ");
    if(!Object.Equals(oi1, oi2))
        printf("NO ");
    printf("son iguales.\n");

    Object.Set(oi2, 5);
    
    printf("valor de oi1: %d\n", Object.Get(oi1));
    printf("valor de oi2: %d\n", Object.Get(oi2));
    
    printf("oi1 y oi2 ");
    if(!Object.Equals(oi1, oi2))
        printf("NO ");
    printf("son iguales.\n");
   
    Object.Free(oi1);
    puts("oi1 liberado.");
    
    Object.Free(oi2);
    puts("oi2 liberado.");
}

You cannot allocate memory using obj_instance as an argument for malloc. I mean, this code must fail:

obj_instance *un_objeto = malloc(sizeof(obj_instance));

Object is an instance of obj_instance? How can I encapsulate obj_instance?

  • Does this library you have to create have the concept of classes? It seems to me that in the end, these objects are just being unusual ways of encapsulating ints.

  • I think so, I’m reading a book on object-oriented programming in C

  • You can give an example of code where the object is used for something more complicated than just one int encapsulated? Or is this something that will only be covered in later chapters of the book and the idea here is just to pave the way for more advanced concepts that will be introduced later?

1 answer

3


I don’t know if this is what you need exactly, but to achieve the purpose you ask, I would do the following:

Filing cabinet "object.h":

typedef struct obj_instance obj_instance;

typedef struct Object_vtable {
    void (*Set)(obj_instance *, int);
    int (*Get)(obj_instance *);
    int (*Equals)(obj_instance *, obj_instance *);
    obj_instance *(*New)();
    void (*Free)();
} Object_vtable;

extern Object_vtable Object;

void object_init();

Filing cabinet "object.c":

import "object.h"

typedef struct obj_instance {
    int value;
} obj_instance;

Object_vtable Object;

void Set(obj_instance *instance, int value) {
    instance->value = value;
}

int Get(obj_instance *instance) {
    return instance->value;
}

int Equals(obj_instance *a, obj_instance *b) {
    return a->value == b->value;
}

obj_instance *New() {
    obj_instance *instance = (obj_instance *) malloc(sizeof(obj_instance));
    instance->value = 0;
    return instance;
}

void Free(obj_instance *instance) {
    free(instance);
}

void object_init() {
    Object.New = New;
    Object.Free = Free;
    Object.Equals = Equals;
    Object.Get = Get;
    Object.Set = Set;
}

The idea here is to use a vtable, basically a structure that contains multiple pointers to functions. This is the analog to a class and each of these function pointers is the analog to a method.

The structure Object is the type Object_vtable, and there is only one of those declared statically. It serves as the definition of a class.

The malloc exists within the object.c. But the attempt to do so in main.c will go wrong because the header object.h contains only typedef struct obj_instance obj_instance. Trying to access the attribute value directly on main.c will also give compilation error (it is private). Thus, when analyzing the main.c, compiler will know that there is a structure called obj_instance, but you won’t know its contents, so you won’t know its size either sizeof of malloc will fail. This information will only be available to the compiler within the object.c and will only appear to the program as a whole in the linkediting step.

This is still something quite primitive in transforming C into an object-oriented language. There is still no concept of subclasses, polymorphism or interfaces, although there is already something that will become a constructor, a destructor and some methods. You can also get an idea how to implement the concept of public and private, since in this resulting code, the attribute value is private and the methods are public. Methods such as is_instance and get_class will also be useful further forward, as well as making the structures that represent the classes also, themselves, objects. All this, you will implement later.

  • type of data obj_instance they can only be accessed through the library functions Object.Función; I apologize’m at work and I can’t compile thank you very much for your response seriously

  • @cheroky What build error you had?

  • I can’t compile because I’m at work I just wanted to know if the obj_instance objects can only be accessed through Object.set Object.get functions etc. only member functions

  • @Yes, just what’s in object.h is visible within the main.h. The other parts that are in the object.c are encapsulated and are private.

  • Thank you very much when I get home I’ll start studying your code

Browser other questions tagged

You are not signed in. Login or sign up in order to post.