473,395 Members | 1,938 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 473,395 software developers and data experts.

Suggestion


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 / ha***@stud.ntnu.no ]
Jul 22 '05 #1
10 1376
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
Jul 22 '05 #2
"Eivind Grimsby Haarr" <ha***@stud.ntnu.no> wrote in message
news:Pi*******************************@tiger.stud. 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
Jul 22 '05 #3
"Phlip" <ph*******@yahoo.com> wrote in message
news:i5******************@newssvr33.news.prodigy.c 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

Jul 22 '05 #4
On Mon, 6 Sep 2004 22:50:42 UTC, Eivind Grimsby Haarr <ha***@stud.ntnu.no>
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

Jul 22 '05 #5
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
Jul 22 '05 #6
* 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?
Jul 22 '05 #7
"Eivind Grimsby Haarr" <ha***@stud.ntnu.no> wrote in message
news:Pi*******************************@tiger.stud. 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
Jul 22 '05 #8
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
Jul 22 '05 #9
"Phlip" <ph*******@yahoo.com> wrote in message
news:ax******************@newssvr33.news.prodigy.c 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.
Jul 22 '05 #10
Aguilar, James wrote:
Phlip wrote:
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?
I have never tried it. However...
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


The first time that algorithm renames an innocent bystander, you will feel
bad, and stop using it.

When folks use a refactoring browser in a softer language that permits them,
they fly, because the browser cannot make a mistake.

My C++ code routinely screws up the intellisense and code browsing system in
my Visual Studio editors. They use "just a little language parser" like you
recommend. They don't use the real C++ compiler's program database, because
they want to change their browsing on the fly as I add statements. So we get
the worst of both worlds. My intellisense breaks when the wind blows, and my
browser can't find variables that the compiler can.

If a C++ refactoring browser were this unstable, nobody could tell when it
was adding bugs, so nobody would use it.

--
Phlip
http://industrialxp.org/community/bi...UserInterfaces
Jul 22 '05 #11

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

11
by: John Wellesz | last post by:
Hello, It would be great if there was an option to tell PHP to let the user manage all the HTTP headers instead of sending what it thinks is good for the programmer... For example when you...
5
by: John | last post by:
Hi: I'd like to implement a simple map, which is a 2-D plane with many points, e.g., 100. The points are not evenly distributed, i.e., some points may have two neighbor points; some may have 5...
10
by: Paulo Jan | last post by:
Hi all: Let's say I'm designing a database (Postgres 7.3) with a list of all email accounts in a certain server: CREATE TABLE emails ( clienteid INT4, direccion VARCHAR(512) PRIMARY KEY,...
7
by: J.Marsch | last post by:
I don't know whether this is the appropriate place to give product feedback, but here goes: I would love to see some kind of diagnostic to let me know when implicit boxing has occurred. We...
2
by: vinay | last post by:
I have a scenario, need your suggestion.. Our clients are already using the forms authentication where we check the User/Pwd from SQL svr Database. We also have some SETTINGS for the user saved...
13
by: sandeep chandra | last post by:
Hey guys, I am new to this group.. i never know wot s going on in this group.. but wot made be brought here is cpp.. guys am currently a part of onw reaserch ... am new to everything.. i...
17
by: Jedrzej Miadowicz | last post by:
I recently (re)discovered data binding in Windows Forms thanks to its advances in Visual Studio 2005. As I looked a little deeper, however, I realize that it still suffers from an irksome tendency...
4
by: John Salerno | last post by:
I apologize for the slightly off-topic nature, but I thought I'd just throw this out there for anyone working on text editors or IDEs with auto-completion. I think it should be a feature, when...
20
by: Allan Ebdrup | last post by:
I have a suggestion for C# I would like reader/writer locks to be built in to the language. When you want to aquire a loct on an object o you write lock(o) { ...//critical region } I would...
0
by: Charles Arthur | last post by:
How do i turn on java script on a villaon, callus and itel keypad mobile phone
0
by: ryjfgjl | last post by:
In our work, we often receive Excel tables with data in the same format. If we want to analyze these data, it can be difficult to analyze them because the data is spread across multiple Excel files...
0
by: emmanuelkatto | last post by:
Hi All, I am Emmanuel katto from Uganda. I want to ask what challenges you've faced while migrating a website to cloud. Please let me know. Thanks! Emmanuel
0
BarryA
by: BarryA | last post by:
What are the essential steps and strategies outlined in the Data Structures and Algorithms (DSA) roadmap for aspiring data scientists? How can individuals effectively utilize this roadmap to progress...
1
by: nemocccc | last post by:
hello, everyone, I want to develop a software for my android phone for daily needs, any suggestions?
0
by: Hystou | last post by:
Most computers default to English, but sometimes we require a different language, especially when relocating. Forgot to request a specific language before your computer shipped? No problem! You can...
0
Oralloy
by: Oralloy | last post by:
Hello folks, I am unable to find appropriate documentation on the type promotion of bit-fields when using the generalised comparison operator "<=>". The problem is that using the GNU compilers,...
0
jinu1996
by: jinu1996 | last post by:
In today's digital age, having a compelling online presence is paramount for businesses aiming to thrive in a competitive landscape. At the heart of this digital strategy lies an intricately woven...
0
tracyyun
by: tracyyun | last post by:
Dear forum friends, With the development of smart home technology, a variety of wireless communication protocols have appeared on the market, such as Zigbee, Z-Wave, Wi-Fi, Bluetooth, etc. Each...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.