You are worried about code duplication, but I'm afraid it clouded your mind.
I know that DRY receives a lot of press (and for good reason), but you misunderstood it. There is a difference between non-duplicate code and not duplicate functionality.
DRY does not duplicate functionality. There may be code templates that look the same, but are used for different purposes, which should not merge, since each goal can move independently (and not merging is a nightmare). Their disassembly is random.
Here. You arbitrarily force int* ptr_ in the Base class (which doesn't use it) because, of course, all derived classes will need it. How did you know that? At the moment, it turns out that all derived classes are really needed, but this is a coincidence. They could rely on something else.
Therefore, a reasonable design is to provide an interface in the base class and leave it for each derived class to choose its own implementation:
class Base { public: virtual ~Base() {} }; class D1: public Base { public: D1(Foo const& f): ptr_(new Foo(f)) {} private: std::unique_ptr<Foo> ptr_; }; class D2: public Base { public: D2(Bar const& f): ptr_(new Bar(f)) {} private: std::unique_ptr<Bar> ptr_; };
On the other hand, if the Base class was supposed to provide some general functionality that required data, then, of course, they could be implemented in the implementation of the Base class ... although it can be argued that this is a premature optimization, since again some derivatives classes can do something differently.
Matthieu M.
source share