Search code examples
c++coopprocedural-programming

Are there advantages to the C approach over the C++ approach at times?


I've been mulling this over in my head lately. Most of us are well aware that in C, in order to create a struct, you normally prefix it with a typedef to avoid calling the struct keyword before referencing the object. Of course, C is limited to structs rather than classes. To compensate for this, C tends to use global functions dedicated to a struct to create an object-oriented approach

For example:

typedef struct{
    int foo;
    float bar;
    char* baz;
} SomeStruct;

Vs.

struct AnotherStruct {
    int foo;
    float bar;
    char* baz;
};

AnotherStruct must have the prefix keyword struct before it, when an object of that type is declared within a function. For example:

int main( ... )
{
   struct AnotherStruct obj1; //correct
   SomeStruct obj2; //correct
   struct SomeStruct obj3; //bad
   AnotherStruct obj4; //bad 
}

In terms of the object-oriented approach:

typedef struct {
    //member variables here
} SomeStruct;

SomeStruct* SomeStruct_New( int a, int b, int c )
{
    SomeStruct* obj = calloc( sizeof( SomeStruct ), 1 ); //not sure if that's correct -- been a while since I've used calloc.
    obj.a = a;
    obj.b = b;
    obj.c = c;
    return obj;
}

void SomeStruct_Free( SomeStruct* free )
{
    free( free );
}

These functions are pretty easy to implement without the wrappers - I'm just using them for the sake of example. My point is that, given that you can already create a struct in C++ which doesn't require the typedef to declare without the struct keyword, and using non encapsulated functions which pertained to these structs for an object-oriented approach, I was curious to know if there are any advantages to the C approach of coding in C++, which would include using static global functions as private member functions, along with global function constructors which would return pointers to objects.

This is just mainly out of curiosity, as there are times where I feel like taking the C approach just for the sake of taking it, but this may just be a preferential thing.


Solution

  • It is pretty hard to understand the gist of the question. It seems to me that your main interrogation is whether:

    • "simple" data + functions

    is better than

    • objects

    in some situations.

    No. It's equivalent.

    With the exception of exceptions (!) any code that you express in C++ can be expressed in C. It is just a matter of syntactic sugar that make the C++ counterpart easier to read. And before the naysayers jump on the bandwagon, yes virtual tables can be emulated in C.

    Still, I would rather use C++. Compiler-checked encapsulation (private), compiler-driven overload selection, compiler-boilerplate (templates). It is just syntactic sugar, but such sweet sugar.

    That being said:

    class Foo {
      Foo() {}
    
      friend Foo build(int a, int b);
      friend int getA(Foo const& foo);
      friend int getB(Foo const& foo);
    
      int a;
      int b;
    };
    

    can be thought of as Object Oriented.

    EDIT: simple and dummy example of polymorphism.

    #include <stdio.h>
    
    // Interface
    typedef void (*FunctionPrint)(void const*);
    
    typedef struct {
      FunctionPrint print;
    } PrinterInterface;
    
    void print(void const* item, PrinterInterface const* pi) {
      (*pi->print)(item);
    }
    
    // Foo
    typedef struct { int a; } Foo;
    
    void printFoo(void const* arg) {
      Foo const* foo = (Foo const*)arg;
      printf("Foo{%d}\n", foo->a);
    }
    
    PrinterInterface const FooPI = { &printFoo };
    
    // Bar
    typedef struct { char* a; } Bar;
    
    void printBar(void const* arg) {
      Bar const* bar = (Bar const*)arg;
      printf("Bar{\"%s\"}\n", bar->a);
    }
    
    PrinterInterface const BarPI = { &printBar };
    
    // Main
    int main() {
      Foo foo = { 1 };
      Bar bar = { "Hello, World!" };
    
      print(&foo, &FooPI);
      print(&bar, &BarPI);
    }
    

    Result:

    Foo{1}
    Bar{"Hello, World!"}