Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to merge two classes with much the same code but operating on different structures

I am trying to improve the existing C++ code by removing duplicated code, but cannot come up with a convincing way of doing it. Any insight from more experienced C++ colleagues greatly appreciated.

So I have two structure definitions over which I have no control:

struct struct_1
{
...
other_s * s1;
other_s * s2;
other_s * s3;
... //other fields
};

struct struct_2
{
...
other_s * s1;
other_s * s2;
other_s * s3;
... //other fields, different than struct_1, but not that important
};

And finally the code I want to improve. I have two almost identical classes, which operate in the same way on the structure fields of the same names, but the fields come from different structures. The classes do not operate on the structure fields that would be present in only one structure. Here it goes (simplification):

class class_1
{
    struct_1 * s;

    class_1(){
        s = new struct_1(); //the only practical difference
        ...
    }

    void method()
    {
        ...

        //this is simplification, in reality the code is more complex
        //however the same as in class_2
        inner_data += s->s1;
        inner_data += s->s2;
        inner_data += s->s3; 
        ...
    }
    //other methods
};

class class_2
{
    struct_2 * s;

    class_2(){
        s = new struct_2(); //the only practical difference
        ...
    }

    void method()
    {
        ...

        //this is simplification, in reality the code is more complex
        //however the same as in class_1
        inner_data += s->s1;
        inner_data += s->s2;
        inner_data += s->s3; 
        ...
    }
    //other methods
};

I have spent some time trying to rework it but ended up nowhere. My approach was to use only one class class_1, but I couldn't avoid problems with accessing struct_1 and struct_2 without multiple if's scattered around. Thank you for your help!

like image 566
youri Avatar asked Mar 22 '23 18:03

youri


2 Answers

C++ has a templates for this:

template<typename T>
class MyClass
{
    T* s;

    MyClass(){
        s = new T(); //the only practical difference
        ...
    }

    void method()
    {
        ...

        //this is simplification, in reality the code is more complex
        //however the same as in class_2
        inner_data += s->s1;
        inner_data += s->s2;
        inner_data += s->s3; 
        ...
    }
    //other methods
};

Now you can use your classes as:

MyClass<struct_1> a;

and

MyClass<struct_2> b;

and compiler will generate definitions for these classes based on your template.

Don't forget to deallocate memory in your destructor!

like image 115
Nemanja Boric Avatar answered Apr 26 '23 19:04

Nemanja Boric


You're looking for a template:

template <typename S>
class C {
    S * s;

    C() s(new S()) {}

    void method() {
        // This is all fine as long as `S` has these members
        inner_data += s->s1;
        inner_data += s->s2;
        inner_data += s->s3;
    }
};

Then your classes can be specialisations of this:

typedef C<struct_1> class_1;
typedef C<struct_2> class_2;

(And, hopefully, your real code follows the Rule of Three, since it's messing around with low-level memory allocation.)

like image 35
Mike Seymour Avatar answered Apr 26 '23 18:04

Mike Seymour