Creating a personalized class of Object type in C#

Feedback

Question:

Given the absence of dynamic memory allocation and the requirement to use C instead of C++ or object-oriented compilers, what techniques can be employed to create a class or a close approximation? Is it advisable to have the “class” in a distinct file at all times? It is assumed that the memory can be pre-allocated by defining a constant reference to each object before compile time or assuming a fixed number of instances. Depending on the
OOP concept
to be implemented, different approaches may be recommended.

Restrictions:

  • Since I’m developing software for an embedded system, and the existing codebase and compiler are in C, I am required to use C instead of an OOP approach.
  • Due to insufficient memory, dynamic memory allocation is not possible as there is a risk of running out of memory if we attempt to allocate dynamically.
  • There are no issues with
    function pointers
    when working with the compilers we use.


Solution 1:

The inclusion of function pointers in structures may be necessary if you require object-oriented features such as overloading and virtual methods.

typedef struct {
  float (*computeArea)(const ShapeClass *shape);
} ShapeClass;
float shape_computeArea(const ShapeClass *shape)
{
  return shape->computeArea(shape);
}

You can create a class by inheriting the base class and implementing a function that fits your needs.

typedef struct {
  ShapeClass shape;
  float width, height;
} RectangleClass;
static float rectangle_computeArea(const ShapeClass *shape)
{
  const RectangleClass *rect = (const RectangleClass *) shape;
  return rect->width * rect->height;
}

To ensure that the function pointer is correctly set up, you must implement a constructor. Typically, you would dynamically allocate memory for the instance, but the caller can also handle this task.

void rectangle_new(RectangleClass *rect)
{
  rect->width = rect->height = 0.f;
  rect->shape.computeArea = rectangle_computeArea;
}

To have multiple constructors, it’s necessary to modify the function names with decorations as you cannot have more than one

rectangle_new()

function.

void rectangle_new_with_lengths(RectangleClass *rect, float width, float height)
{
  rectangle_new(rect);
  rect->width = width;
  rect->height = height;
}

Below is a simple demonstration of how it can be used.

int main(void)
{
  RectangleClass r1;
  rectangle_new_with_lengths(&r1, 4.f, 5.f);
  printf("rectangle r1's area is %f units squaren", shape_computeArea(&r1));
  return 0;
}

Hopefully, this will provide you with some inspiration. To achieve a thriving and well-structured object-oriented framework in C, consider exploring the GObject library of glib.

It’s worth noting that the above model does not incorporate an explicit “class”. Instead, each object possesses its own
method pointers
, which provides greater flexibility compared to the usual C++ practice. However, this approach incurs memory overhead. To mitigate this, you can store the method pointers in a

class

structure and devise a mechanism for each object instance to reference a class.


Solution 2:


For a homework assignment, I also had to do it once and utilized the following method:

  1. Declare your variables within a struct.
  2. Create function members that have a struct pointer as their initial parameter.
  3. Combine the struct definition and function declarations in a single header file, while keeping the implementations in a separate C file.

A simple example would be this:

/// Queue.h
struct Queue
{
    /// members
}
typedef struct Queue Queue;
void push(Queue* q, int element);
void pop(Queue* q);
// etc.
/// 


Solution 3:


To create a single class, utilize an array consisting of

struct

s as the data for the “objects” and provide pointers to the “member” functions. Prior to declaring

struct _whatever

, you may opt to use

typedef struct _whatever Whatever

to conceal the implementation from the client code. It is important to note that there is no distinction between this type of “object” and the C standard library’s

FILE

object.

To implement multiple classes with inheritance and
virtual functions
, it is typical to include function pointers as members of a struct or a reference to a table of virtual functions. The GObject library employs both of these techniques and is frequently utilized.

Online, one can access a guide on the methods for this topic, which is known as
object oriented programming with ansi c
.


Solution 4:

David R. Hanson’s book, C Interfaces and Implementations, provides techniques for developing software that can be reused.

This website offers a product that can be found at the following URL: http://www.informit.com/store/product.aspx?isbn=0201498413

The Addison Wesley Professional Computing series successfully addresses your inquiry in this book.

The fundamental framework can be explained as follows:

/* for data structure foo */
FOO *myfoo;
myfoo = foo_create(...);
foo_something(myfoo, ...);
myfoo = foo_append(myfoo, ...);
foo_delete(myfoo);

Frequently Asked Questions