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!
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!
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.)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With