Possible to require overloading of a non-pure method?

R

[rob desbois]

Hi all, I have a set of classes which implement the virtual
constructor idiom.

I had a slicing problem which resulted when I forgot to override the
clone() function in a derived class.

Is there something (other than documentation) that I can do to prevent
this from happening again?

TIA,
--rob
 
R

[rob desbois]

Unit testing and code reviews.

Allow me to clarify. I meant is there any language construct which can
enforce this requirement.

A unit test wouldn't have helped -- I'd have had to remember to write
a unit test for the new class's clone() method ensuring that the
returned pointer is castable to a pointer to the new derived type. If
I'd have remembered that I'd have remembered to code the clone method
anyway.

--rob
 
T

Thomas J. Gritzan

Allow me to clarify. I meant is there any language construct which can
enforce this requirement.

A unit test wouldn't have helped -- I'd have had to remember to write
a unit test for the new class's clone() method ensuring that the
returned pointer is castable to a pointer to the new derived type. If
I'd have remembered that I'd have remembered to code the clone method
anyway.

"Design by Contract".

Something like (untestet):

class Base
{
public:
Base* clone() const
{
Base* p = doClone();
assert(typeid(*p) == typeid(*this));
return p;
}

private:
Base* doClone() const
{
return new Base(*this);
}
}
 
R

[rob desbois]

Thomas said:
On 2008-04-25 06:40:20 -0400, "[rob desbois]"
<[email protected]> said:
Hi all, I have a set of classes which implement the virtual
constructor idiom.
I had a slicing problem which resulted when I forgot to override
the clone() function in a derived class.
Is there something (other than documentation) that I can do to
prevent this from happening again?
Unit testing and code reviews.
Allow me to clarify. I meant is there any language construct which
can enforce this requirement.
A unit test wouldn't have helped -- I'd have had to remember to write
a unit test for the new class's clone() method ensuring that the
returned pointer is castable to a pointer to the new derived type. If
I'd have remembered that I'd have remembered to code the clone method
anyway.
"Design by Contract".
Something like (untestet):
class Base
{
public:
   Base* clone() const
   {
      Base* p = doClone();
      assert(typeid(*p) == typeid(*this));
      return p;
   }
private:
   Base* doClone() const
   {
      return new Base(*this);
   }
}

    ;

First off, no virtual functions here, did you mean to make 'doClone'
virtual?  And second, he needed the compile-time solution, AIUI.

I expect he did.
And how does 'typeid' trick work?  Does 'typeid' return the dynamic
type of '*this'?  So, if you derive from 'Base', what then?  How
does the splitting of the function in two help _forcing_ the derived
class provide the override?

typeid is part of C++'s runtime type identification (RTTI)
functionality and yes, provides a dynamic type identifier of 'this'.
If I derive from Base without overriding doClone(), then the assertion
fails:
assert(typeid(*p) == typeid(*this));
because *p is a Base and *this is a Derived.

--rob
 
R

[rob desbois]

On 2008-04-25 06:40:20 -0400, "[rob desbois]" <[email protected]> said :
Hi all, I have a set of classes which implement the virtual
constructor idiom.
I had a slicing problem which resulted when I forgot to override the
clone() function in a derived class.
Is there something (other than documentation) that I can do to prevent
this from happening again?
Unit testing and code reviews.
Allow me to clarify. I meant is there any language construct which can
enforce this requirement.
A unit test wouldn't have helped -- I'd have had to remember to write
a unit test for the new class's clone() method ensuring that the
returned pointer is castable to a pointer to the new derived type. If
I'd have remembered that I'd have remembered to code the clone method
anyway.

Unit tests would have helped, if they are written correctly and
reviewed correctly. What you're asking for is a language mechamism to
compensate for a weak development process. Fix the process.

The language, its syntax, and libraries are there to support the
developer and the development process.
Would you suggest that using assert() is a weak development process?

Assuming that you were developing this and made the same basic mistake
that I did here -- forgot to override clone() -- where exactly would
the mistake have been spotted?
A correctly written unit test? I forgot to implement clone() so would
likely have forgotten the test for it.
A correctly reviewed unit test? In a team of 2 developers in a small
company developing specialised software, where I have the most
experience, I think it unlikely that it would've been caught.

Is there something else I could've done?

--rob
 
J

James Kanze

Thomas said:
On 2008-04-25 06:40:20 -0400, "[rob desbois]"
<[email protected]> said:
Hi all, I have a set of classes which implement the virtual
constructor idiom.
I had a slicing problem which resulted when I forgot to override
the clone() function in a derived class.
Is there something (other than documentation) that I can do to
prevent this from happening again?
Unit testing and code reviews.
Allow me to clarify. I meant is there any language
construct which can enforce this requirement.
A unit test wouldn't have helped -- I'd have had to
remember to write a unit test for the new class's clone()
method ensuring that the returned pointer is castable to a
pointer to the new derived type. If I'd have remembered
that I'd have remembered to code the clone method anyway.
"Design by Contract".

(That should be "Programming by Contract" here. It's a coding
issue, not a design issue.)
First off, no virtual functions here, did you mean to make
'doClone' virtual?
Obviously.

And second, he needed the compile-time solution, AIUI.

You take what you can get:).

I think I'm the one who actually invented this technique, at
least with regards to using typeid for cloning. In practice,
however, I find that this particular bit of programming by
contract is simply not worth the extra work (although I tend to
use programming by contract fairly intensively in my work
otherwise). As Pete has said, failing to provide the clone
function is something that simply doesn't slip past code review
and unit tests.
And how does 'typeid' trick work? Does 'typeid' return the dynamic
type of '*this'?

It will if the static type is polymorphic.
So, if you derive from 'Base', what then? How does the
splitting of the function in two help _forcing_ the derived
class provide the override?

You get an assertion failure if you attempt to clone a class
which has not implemented the clone function.
 
T

Thomas J. Gritzan


virtual Base* doClone() const
;

First off, no virtual functions here, did you mean to make 'doClone'
virtual? And second, he needed the compile-time solution, AIUI.

First: Yes, I forgot the virtual. That's what code review is for :)
Thanks for that.

Second, there is no compile-time solution for this. You can't force to
override a virtual function.
And how does 'typeid' trick work? Does 'typeid' return the dynamic
type of '*this'? So, if you derive from 'Base', what then? How
does the splitting of the function in two help _forcing_ the derived
class provide the override?

Having a polymorphic class (a class with virtual functions is
polymorphic), typeid(x) returns the dynamic type of x.

In the expression
assert(typeid(*p) == typeid(*this));

typeid(*this) returns the dynamic, run-time type of the current object,
typeid(*p) return the dynamic type of the new object. So, if the clone
doesn't have the exact same type as the current object, the
postcondition of the clone() method is violated.
 
T

Thomas J. Gritzan

James said:
You take what you can get:).

I think I'm the one who actually invented this technique, at
least with regards to using typeid for cloning.

In fact, I've seen it used this way the first time in one of your postings.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
474,175
Messages
2,570,942
Members
47,490
Latest member
Finplus

Latest Threads

Top