Velocity Reviews - Computer Hardware Reviews

Velocity Reviews > Newsgroups > Programming > C++ > Suggestion

Reply
Thread Tools

Suggestion

 
 
Eivind Grimsby Haarr
Guest
Posts: n/a
 
      09-06-2004

When using polymorphism in a big system, I have sometimes come across
problems when changing the signature of the function in the base class,
and forgetting to change the signature of the derived functions
accordingly. (Most often when only some of the derived classes redefine
it.) Accessing the objects with base class pointers, the version in the
base class is called, which is not what I wanted. This is most often very
difficult to detect.

This has made me come up with an idea for a compiler/language feature that
would fix this problem: A keyword in front of the derived function that
says that this function is derived from a base class, and the compiler
should issue an error if a function with a similar signature doesn't
exist in one of the base classes.

What do you think about this idea? Is it just too much pain for a rare
problem?

Maybe anyone have other ideas on how to prevent such problems? Using
macros to declare the signatures is of course one idea, but true
C++-programmers don't like macros, right? (Perfect design and
programming from the beginning would prevent it, of course, but even
programmers are humans...)

Naming the keyword 'isderived', I'll illustrate my idea with an example:

Function f(double) is performing some calculation. In the base class B, a
default calculation is provided, but a few of the many classes that derive
from B has their own implementation.

-------

class B {
virtual double f(double i) {...} // Uups! Forgot to declare 'const'
}

class OneOfManyDerivedClasses : public B {
isderived double f(double i) {...} // Should be derived from base class
}

vector<B*> v;
....
// Fill the vector with objects of different derived classes
....
int sum = 0;
for (it = v.begin(); it != v.end(); ++it) {
sum+=(*v)->f(number);
}

------

If I later change the base class function to const, the function in the
derived class will not be called when iterating through the vector. If
this calculation is part of a complex calculation with many classes, this
is difficult to detect. With the 'isderived' keyword, a compiler error
would be issued, and the problem prevented.


Any views?


Mvh
Eivind Grimsby Haarr

[ 97 07 66 58 / http://www.velocityreviews.com/forums/(E-Mail Removed) ]
 
Reply With Quote
 
 
 
 
Phlip
Guest
Posts: n/a
 
      09-06-2004
Eivind Grimsby Haarr wrote:
>
> When using polymorphism in a big system, I have sometimes come across
> problems when changing the signature of the function in the base class,
> and forgetting to change the signature of the derived functions
> accordingly. (Most often when only some of the derived classes redefine
> it.) Accessing the objects with base class pointers, the version in the
> base class is called, which is not what I wanted. This is most often very
> difficult to detect.
>
> This has made me come up with an idea for a compiler/language feature that
> would fix this problem:


Wouldn't that mistake break all the unit tests that depended on the base
class polymorphing into the derived class's behavior?

--
Phlip
http://industrialxp.org/community/bi...UserInterfaces


 
Reply With Quote
 
 
 
 
Unforgiven
Guest
Posts: n/a
 
      09-06-2004
"Eivind Grimsby Haarr" <(E-Mail Removed)> wrote in message
news(E-Mail Removed). ntnu.no...
>
> When using polymorphism in a big system, I have sometimes come across
> problems when changing the signature of the function in the base class,
> and forgetting to change the signature of the derived functions
> accordingly. (Most often when only some of the derived classes redefine
> it.) Accessing the objects with base class pointers, the version in the
> base class is called, which is not what I wanted. This is most often very
> difficult to detect.
>
> This has made me come up with an idea for a compiler/language feature that
> would fix this problem: A keyword in front of the derived function that
> says that this function is derived from a base class, and the compiler
> should issue an error if a function with a similar signature doesn't
> exist in one of the base classes.
>
> What do you think about this idea? Is it just too much pain for a rare
> problem?


Someone had your idea already. ^_^
The following samples follow VB.NET syntax.

Public Class Base
Public Overridable Sub SomeMethod(ByVal a As Integer)
' Stuff
End Sub
End Class

Public Class Child
Inherits Base
Public Overrides Sub SomeMethod(ByVal a As Integer)
' Stuff
End Sub
End Class

As you can see, the "Overrides" keyword does what you describe. Leave it
out, and the compiler will tell you "sub 'SomeMethod' shadows an overridable
method in a base class. To override the base method, this method must be
declared 'Overrides'." This is a warning not an error, but if ignored, as
the message indicates, the method will shadow (hide) the base class method,
not override it, which means any polymorphic calls to a Base reference that
is really a Child will always access the Base SomeMethod. If that's the
behaviour you want but want to get rid of the warning, you should add the
"Shadows" keyword, which tells the compiler explicitly that that is what you
want to do.

If you were to change the signature of SomeMethod in the base class (with
Overrides on the child class method declaration), for instance have
parameter "a" be a Double instead of an Integer, the compiler will give you
both the error "sub 'SomeMethod' cannot be declared 'Overrides' because it
does not override a sub in a base class." and the warning "sub 'SomeMethod'
shadows an overloadable member declared in the base class 'Base'. If you
want to overload the base method, this method must be declared 'Overloads'."

As you can see, you're not the only one who thinks this kind of behaviour
would be a good idea. I know it's one of the VB.NET language features I
appreciate. ^_^

--
Unforgiven


 
Reply With Quote
 
Unforgiven
Guest
Posts: n/a
 
      09-06-2004
"Phlip" <(E-Mail Removed)> wrote in message
news:i56%c.14750$(E-Mail Removed) om...
> Eivind Grimsby Haarr wrote:
>>
>> When using polymorphism in a big system, I have sometimes come across
>> problems when changing the signature of the function in the base class,
>> and forgetting to change the signature of the derived functions
>> accordingly. (Most often when only some of the derived classes redefine
>> it.) Accessing the objects with base class pointers, the version in the
>> base class is called, which is not what I wanted. This is most often very
>> difficult to detect.
>>
>> This has made me come up with an idea for a compiler/language feature
>> that
>> would fix this problem:

>
> Wouldn't that mistake break all the unit tests that depended on the base
> class polymorphing into the derived class's behavior?


Prolly, but that's only *if* you write unit tests ^_~

(And don't anyone dare reply you should always write unit tests, I was being
sarcastic damnit!)

--
Unforgiven

 
Reply With Quote
 
David
Guest
Posts: n/a
 
      09-07-2004
On Mon, 6 Sep 2004 22:50:42 UTC, Eivind Grimsby Haarr <(E-Mail Removed)>
wrote:

>
> When using polymorphism in a big system, I have sometimes come across
> problems when changing the signature of the function in the base class,
> and forgetting to change the signature of the derived functions
> accordingly. (Most often when only some of the derived classes redefine
> it.) Accessing the objects with base class pointers, the version in the
> base class is called, which is not what I wanted. This is most often very
> difficult to detect.


My solution, is that the person(s) responsible for the change have to
insure their change does not adversely affect the rest of the system.
For a big system, this may mean examining all the source or issuing
some kind of announcement to a development group. Since it sounds like
you have control of the system and the ability to do a full compile,
it should have been possible to find all uses and verify that your
proposed change could safely be made. On occasion, I've intentionally
broken a method to help find all its users during a local build.

For the "test case" crowd, it might be sufficient to change some of
the tests to insure compatibility. However, I can imagine times where
even a simple change could modify an entire test hierarchy. This is
where I've seen a few TDD groups fall short from inexperience. It can
be difficult to make such a change and then find all the uses and
implications of that change.

<snip>

David

 
Reply With Quote
 
Phlip
Guest
Posts: n/a
 
      09-07-2004
David wrote:

> My solution, is that the person(s) responsible for the change have to
> insure their change does not adversely affect the rest of the system.


ensure

> For a big system, this may mean examining all the source or issuing
> some kind of announcement to a development group. Since it sounds like
> you have control of the system and the ability to do a full compile,
> it should have been possible to find all uses and verify that your
> proposed change could safely be made. On occasion, I've intentionally
> broken a method to help find all its users during a local build.


A symetric typographical error could create the issue. Then you don't know
you should announce or rebuild.

> For the "test case" crowd, it might be sufficient to change some of
> the tests to insure compatibility. However, I can imagine times where
> even a simple change could modify an entire test hierarchy. This is
> where I've seen a few TDD groups fall short from inexperience.


"groups"? You mean TDD-ing teams?

I use TDD to generate behavior, then I refactor that behavior into an object
model. The behaviors might go here or there, but the tests that created each
one still (in theory) demand them to exist. So (in theory), if that behavior
now routes thru virtual functions, the tests would detect failure if the
virtuality breaks.

I could look at my C++ TDD programs that inherit, and see if breaking the
virtual link will break a test. In theory.

In practice, one can use the Abstract Test pattern to mirror production type
hierarchies to test hierarchies. However, they tend to prove that all
derived classes behaved the same, not different.

> It can
> be difficult to make such a change and then find all the uses and
> implications of that change.


Were all those uses themselves invented via TDD?

--
Phlip
http://industrialxp.org/community/bi...UserInterfaces


 
Reply With Quote
 
Alf P. Steinbach
Guest
Posts: n/a
 
      09-07-2004
* Eivind Grimsby Haarr:
>
> When using polymorphism in a big system, I have sometimes come across
> problems when changing the signature of the function in the base class,
> and forgetting to change the signature of the derived functions
> accordingly. (Most often when only some of the derived classes redefine
> it.) Accessing the objects with base class pointers, the version in the
> base class is called, which is not what I wanted. This is most often very
> difficult to detect.
>
> This has made me come up with an idea for a compiler/language feature that
> would fix this problem: A keyword in front of the derived function that
> says that this function is derived from a base class, and the compiler
> should issue an error if a function with a similar signature doesn't
> exist in one of the base classes.
>
> What do you think about this idea? Is it just too much pain for a rare
> problem?


It's always a good idea to catch errors at the earliest time possible,
preferably analysis and design, but if not, then compile-time.

Your idea is a Good One (TM) and is implemented in .NET languages such as
VB.NET and C#, in the latter using the keywords "override" (override) and
"new" (shadow).

Getting it into C++, that's another matter...

--
A: Because it messes up the order in which people normally read text.
Q: Why is it such a bad thing?
A: Top-posting.
Q: What is the most annoying thing on usenet and in e-mail?
 
Reply With Quote
 
Aguilar, James
Guest
Posts: n/a
 
      09-07-2004
"Eivind Grimsby Haarr" <(E-Mail Removed)> wrote in message
news(E-Mail Removed). ntnu.no...
>
> [snip]


It would be an interesting exercise to write a C++ program that would
recurse into a directory structure and find all instances of a method
(search for : public \ClassName/ then find the method (if it exists)
within), and replace them. You could call it "rename". =)

I don't know if you have time, but it seems like a pro would not take all
that long to whip up something like this, even if it is platform dependent.

James


 
Reply With Quote
 
Phlip
Guest
Posts: n/a
 
      09-07-2004
Aguilar, James wrote:

> It would be an interesting exercise to write a C++ program that would
> recurse into a directory structure and find all instances of a method
> (search for : public \ClassName/ then find the method (if it exists)
> within), and replace them. You could call it "rename". =)
>
> I don't know if you have time, but it seems like a pro would not take all
> that long to whip up something like this, even if it is platform

dependent.

It's the first feature of a "refactoring browser" - rename identifier. To
learn how "easy" that is, search the net for a refactoring browser for C++.

--
Phlip
http://industrialxp.org/community/bi...UserInterfaces


 
Reply With Quote
 
Aguilar, James
Guest
Posts: n/a
 
      09-07-2004
"Phlip" <(E-Mail Removed)> wrote in message
news:axb%c.14832$(E-Mail Removed) om...
>
> It's the first feature of a "refactoring browser" - rename identifier. To
> learn how "easy" that is, search the net for a refactoring browser for
> C++.


I'm making an assumption here that might not be correct, so correct me if
I'm wrong -but- I assume that you are trying to imply that it is not easy (I
don't really want to use my time to search for such a browser right now,
since I personally have no use for it at the moment). Maybe you can explain
why?

In any case, here's my idea for an algorithm:

ALGORITHM :

Inputs: Method signature, set of type name,
directory name *possibly blank for base level call*
Vars: boolean valid (begins false)
Returns: boolean
WHILE (valid) {
0. valid = true;
1. Get all files in this folder **PLATFORM DEPENDENT**
a. remove all files that do not end in extension .cc or .hh (GNU naming
conventions)
2. For each file
a. Continue to eat input until you come to end of file or come to ":
public
\member of set/" or "\methSig&member of set/" (use tokens to process
the input,
basic stuff)
b. If you come to the case described in 2a., valid becomes false and do
step 3,
otherwise, step four
3. Edit "\methSig/" as appropriate and write the file
4. Get list of directories and recurse. If any recursive call returns
false, valid is
set to false.
}

: ALGORITHM

So that would do the part of making sure that within the classes, everything
is changed. The reason for valid is to make sure that if there is a
subclass of a subclass, it is included. It would not rename calls to the
method or check to make sure that the change did not break outside uses of
it, but I think this would accomplish what the OP wants (that is, to prevent
any silent errors from showing up and biting him in the butt later on). It
doesn't seem like it should be -that- hard, but I didn't mean to say it
would be easy, especially for someone of my age in the processes of learning
this stuff.


 
Reply With Quote
 
 
 
Reply

Thread Tools

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
Wireless Access Point Suggestion =?Utf-8?B?UyBMYW5l?= Wireless Networking 2 06-24-2005 10:39 PM
Suggestion for a new name, logo and slogan for the Mozilla Suite... Charles Firefox 2 03-12-2005 04:31 AM
"Read-only" version of Mozilla? (suggestion for a new software idea) Hallvard Tangeraas Firefox 4 01-12-2005 07:24 PM
FireFox-opening new tabs, a suggestion me Firefox 3 09-21-2004 04:19 PM
Re: Suggestion for Cache flush in Moz Caffeine Junkie Firefox 1 01-20-2004 06:06 AM



Advertisments