Say you have a base class Dep
for a tree of classes. There is a virtual method Dep* Dep::create()
that I want to be implemented by every single leaf class. Is there any way to enforce this?
Note: The problem here is that there could be intermediate classes (say class B : public A : public Dep
) implementing this method (A::create
) by accident or because they think they are leaf classes, but are in fact subclassed themselves.
The question ends here.
If you are curious why I need this; I have a class Master
which has Dep
objects of unknown concrete type. If Master
is duplicated, I need to come up with a matching clone of the Dep
instance. Next best thing to do is the virtual constructor idiom, which introduces precisely this problem.
Additionally, I cannot even catch this (other then by crashing horribly), because for obscure reasons, people that have more to say than me, have outlawed dynamic_cast
in this project (perhaps this is a good decision; But anyways a completely different discussion).
C++ provides no way to keep a class from inheriting from your class, and there is no way to make a particular class in the inheritance hierarchy implement a method. The only rule is that somewhere in the inheritance hierarchy above a particular class (not necessarily in the leaf) all virtual functions must have an implementation for that class to be instantiatable.
For instance, A
could inherit from Def
and implement all it's [pure] virtual methods. Then if B
inherits from A
, it doesn't have to implement anything. There's no way to keep that from happening.
So the answer is no, there is no way to enforce this.
Using curiously recurring template fun, you can achieve something quite similar:
template<typename T>
class Cloneable : public T, public Dep
{
private:
Cloneable<T>() : T() { }
public:
static Cloneable<T>* Create() { return new Cloneable<T>(); }
Cloneable<T>* clone() { return new Cloneable<T>(*this); }
};
Instead of deriving from Dep
and instantiating via new MyType
, use Cloneable<MyType>::Create
. Since Cloneable<MyType>
is derived from MyType
, you can use the instance the same way you would use any MyType
, except that it is now guaranteed to have Dep::clone
.
Additionally your Master
should not accept an instance of type Dep
, but enforce that it is a Cloneable<T>
. (Replace your orignial function by a simple function template that enforces this.) This guarantees that any Dep
inside the master has a correctly implemented clone
function.
Since Cloneable<MyType>
has no public constructor, it cannot be inherited, however your actual MyType
can be further inherited and used just as before.
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