tags:

views:

499

answers:

9

How to make sure that all derived C++/CLI classes will override the ICloneable::Clone() method of the base class?

Do you think I should worry about this? Or this is not a responsibility of the base class' writer?

Amendment: Sorry, I forgot to mention that the base class is a non-abstract class.

+1  A: 

Declare the Clone() method as abstract. This should work even when the parent class does have a concrete implementation.

Of course, the risk when enforcing such things is that the writer of the derived class will become annoyed, say "I'm not going to use Clone anyway" and does something like a bytewise copy, or even a "return this", to get rid of the errors.

Thomas
+2  A: 

Declare it pure virtual in the base class.

class Base
{
...
vitual void Clone() = 0;
};

Milan Babuškov
+2  A: 

Well, I can't say if this is the responsibility of the base class or not, and won't get into the perils of inheritance based contracts here.

In any case, you can force some class to override a method - "Clone()" for example, by making it a pure virtual member of an abstract class

public ref class ClonableBase abstract
{
 public:
   virtual void Clone() = 0;
}

note the "abstract" and the "=0;". The abstract allows the class to contain pure virtual members without warning, and the =0; means that this method is pure virtual - that is, it doesn't contain a body. Note that you can not instantiate an abstract class.

Now you can

public ref class ClonableChild : public ClonableBase
{
 public:
   virtual void Clone();
}

void ConableChild::Clone()
{
  //some stuff here
}

If you do NOT have the Clone override in ClonableChild, you get a compiler error.

Philip Rieck
A: 

Thomas is correct but one way you would make that class abstract is to define a pure virtual method.

This is done by saying:

virtual void Clone() = 0;

Unless the derived class implements Clone they won't be able to instantiate it so they'll have little choice if they want their class to be useful.

Jon
A: 
class Base
{
...
virtual void Clone() = 0;
};

is correct.

If you want some default behaviour for Clone, try:

class Base
{
...
virtual void Clone()
{ 
   ...
   doClone();
   ...
};

...

private:
virtual void doClone() = 0;
};
metao
A: 

Amendment: Sorry, I forgot to mention that the base class is a non-abstract class.

In this new light, I'm pretty sure that you do not want to force anyone to override Clone() at all. For example, if my derived class does not add any fields it probably does not need its own specialized Clone() method.

Thomas
Even if your derived class doesn't add any new fields, the ICloneable::Clone() method still has to create and return an object of the right type. baseClassObj->Clone() should return an instance of BaseClass and derivedClassObj->Clone() should return an instance of DerivedClass.
metamal
+1  A: 

If the base class is non-abstract, then there is no way to force it to be overridden at compile time. The best you can probably do is something like:

virtual void Clone()
{
   throw gcnew NotSupportedException();
}

With this, derived classes would have to override the method or your application will encounter a NotSupportedException. This at least would make it immediately obvious during testing that something was incorrect. It would give you something to look for so that you know when you encounter a class that did not correctly override Clone. Depending on how much control you have over derived classes, this could be important for robustness.

alabamasucks
A: 

After some pondering I found this solution:

Object^ BaseClass::Clone()
{
  if(this->GetType() != BaseClass::typeid)
  {
    throw gcnew System::NotImplementedException("The Clone() method is not implemented for " + this->GetType()->ToString() + "!");
  }

  BaseClass^ base = gcnew BaseClass();
  ... // Copy the fields here
  return base;
}

It throws NotImplementedException if you attempt to Clone an instance of a derived class that hasn't overridden the Clone() method of the base class.

metamal
A: 

read this by herb sutter. It's exactly what you are asking

ugasoft