I have got myself into a strange issue now. Ill write a really simplified version of the same.
class Base
{
public:
virtual int func1()=0;
virtual int func2()=0;
protected:
int n;
};
class der1: public Base
{
// implements the virtual functions of the base and uses the protected data
// members of the base.
};
class der2: public Base
{
// implements the virtual functions of the base and uses the protected data
// members of the base.
}
Now the problem.... both der1
and der2
implements the virtual functions of base pretty much the same way. But some other classes (der3
, der4
) has their own implementations. But still need to inherit from base.
How do i refactor the code to remove the code duplication in an oop manner?
Here's one solution using an intermediate layer of another abstract base class:
class Base12 : public Base {
protected:
int commonFuncStuffA() {
// Commonly used stuff
}
int commonFuncStuffB() {
}
};
class der1: public Base12
{
public:
virtual int func1() {
n = commonFuncStuffA();
}
virtual int func2() {
n = somethingElse;
}
};
class der2: public Base12
{
public:
virtual int func1() {
n = commonFuncStuffA();
}
virtual int func2() {
n = commonFuncStuffB();
}
};
What I'd do for real production code design looks a bit different though.
Declare an interface for the pure virtual functions
struct IMyInterface {
virtual int func1() = 0;
virtual int func2() = 0;
virtual ~IMyInterface {}
};
Provide a abstract base class with the commonly used data members and functions
class BaseImpl : public IMyInterface {
protected:
int n;
int commonFuncStuffA() {
// Commonly used stuff
}
int commonFuncStuffB() {
// Commonly used stuff
}
};
Provide implementations of the interface in the finally derived classes
class der1: public BaseImpl {
public:
virtual int func1() {
n = commonFuncStuffA();
}
virtual int func2() {
n = somethingElse;
}
};
class der2: public BaseImpl {
public:
virtual int func1() {
n = commonFuncStuffA();
}
virtual int func2() {
n = commonFuncStuffB();
}
};
class der3: public IMyInterface {
public:
virtual int func1() {
// Some completely different implementation of the interface
}
virtual int func2() {
// Some completely different implementation of the interface
}
};
class der4: public IMyInterface {
public:
virtual int func1() {
// Some completely different implementation of the interface
}
virtual int func2() {
// Some completely different implementation of the interface
}
};
You may consider using your most common implementation in the Base
class. The main feature or drawback of this method is that the base class would no longer be abstract. If this is a problem, go to option 2.
Maybe you can even cope with differences in the derived classes by using the template method pattern to extract the differences in protected virtual functions invoked by the template method.
In anyway, for derived classes that need a completely different appoach, you'd just override the the Base class' method.
class Base
{
public:
virtual int func1();
virtual int func2()=0;
protected:
virtual void f1_specific_part1()=0;
virtual void f1_specific_part2()=0;
int n;
};
int Base::func1() { // common skeleton of the algorithm
...
f1_specific_part1();
...
f1_specific_part2();
...
}
class Der1: public Base
{
protected:
void f1_specific_part1() override; // Implements the specific variation
virtual void f1_specific_part2() override;
};
You may consider to factorize the common code of the derived classes into a protected method of the Base
class.
The override of the pure virtual function would then just call the base class protected common function (for der1
and der2
) or just use their own implementation that is completely different (for der3
and der4
).
class Base
{
public:
virtual int func1()=0;
virtual int func2()=0;
protected:
int common_part1_funct1(); // implements some common parts
int common_part2_funct1();
int n;
};
class Der1: public Base
{
...
int func1() override {
common_part1_funct1();
...
common_part2_funct1();
...
}
};
Important remark: My answer assumes that there are many commonalities between most of the derived classes. However if you have only a small subset of derived classes that share some commonalities, then the answer of Evg would be would be more appropriate.
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