By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
454,435 Members | 1,493 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 454,435 IT Pros & Developers. It's quick & easy.

How to determine if virtual function in base class is overriden?

P: n/a
I have a base class, PadRcv, with virtual functions. User code
will derive from this class and possibly supply it's own functions
to override the base class virtual functions. How can I test that
a user-defined class has overriden the virtual function in the
base class?

I have code like this which compiles with gcc 2.95.4:

Attrib Implicits(PadRcv *obj){
Attrib accum = 0;
PadRcv *padrcv;

if( !obj ) return 0;
char* (PadRcv::*pmfa)(char *) = &PadRcv::kbd;
void (PadRcv::*pmfb)() = &PadRcv::userclose;
if( obj->*pmfa != &PadRcv::kbd ) accum |= ACCEPT_KBD;
if( obj->*pmfb != &PadRcv::userclose ) accum |= USERCLOSE;
return accum;
}

With gcc 3.4.4, I get the following errors:

pad.C: In function `Attrib Implicits(PadRcv*)':
pad.C:27: error: invalid use of non-static member function
pad.C:28: error: invalid use of non-static member function
*** Error code 1

There is plenty of documentation on the net for pointers to member
functions and virtual functions but nothing seems to cover this
particular area.

Dec 20 '06 #1
Share this Question
Share on Google+
6 Replies


P: n/a
<no*******@gmail.comwrote:
>I have a base class, PadRcv, with virtual functions. User code
will derive from this class and possibly supply it's own functions
to override the base class virtual functions. How can I test that
a user-defined class has overriden the virtual function in the
base class?
Cannot some debugger interfaces unwind the class structure
and expose its hierarchy, including information like this?

I think, anyway, this is a tools question if the problem
can be solved by manual examination.

Steve
Dec 20 '06 #2

P: n/a
On Dec 20, 7:38 am, noel.h...@gmail.com wrote:
I have a base class, PadRcv, with virtual functions. User code
will derive from this class and possibly supply it's own functions
to override the base class virtual functions. How can I test that
a user-defined class has overriden the virtual function in the
base class?
Why would you like to know, I find that it kind of goes against the
whole idea of virtual functions, you don't need to know if it's the
base's function or the derived's.

--
Erik Wikström

Dec 20 '06 #3

P: n/a

no*******@gmail.com wrote:
I have a base class, PadRcv, with virtual functions. User code
will derive from this class and possibly supply it's own functions
to override the base class virtual functions. How can I test that
a user-defined class has overriden the virtual function in the
base class?
You can't "test" if the user overode the virtual function other than by
observing the result. What you can do is provide a pure virtual member
function in the base class which means the user can't compile a
derivative class unless that pure virtual is indeed implemented.
>
I have code like this which compiles with gcc 2.95.4:

Attrib Implicits(PadRcv *obj){
Attrib accum = 0;
PadRcv *padrcv;

if( !obj ) return 0;
char* (PadRcv::*pmfa)(char *) = &PadRcv::kbd;
void (PadRcv::*pmfb)() = &PadRcv::userclose;
You could identify the type of object through RTTI where <typeinfo>
will let you resolve the type of the object at the pointer, if any.

#include <typeinfo>
....
int Implicits(PadRcv *obj){
if( !obj ) return 0;
std::cout << "the object at *obj is of type:";
std::cout << typeid(*obj).name() << std::endl;
...
}

Judging from the error you are getting and the code here, something
else is going on. In particular, you are *not* attempting to call a
member function on the object, but rather on the class - hence the
error about "invalid use of non-static member function". That should be
expected at this point.
if( obj->*pmfa != &PadRcv::kbd ) accum |= ACCEPT_KBD;
if( obj->*pmfb != &PadRcv::userclose ) accum |= USERCLOSE;
return accum;
}
Also, treating blocks of char arrays as data is begging for trouble.
>
With gcc 3.4.4, I get the following errors:

pad.C: In function `Attrib Implicits(PadRcv*)':
pad.C:27: error: invalid use of non-static member function
pad.C:28: error: invalid use of non-static member function
*** Error code 1

There is plenty of documentation on the net for pointers to member
functions and virtual functions but nothing seems to cover this
particular area.
Dec 20 '06 #4

P: n/a
* no*******@gmail.com:
I have a base class, PadRcv, with virtual functions. User code
will derive from this class and possibly supply it's own functions
to override the base class virtual functions. How can I test that
a user-defined class has overriden the virtual function in the
base class?

I have code like this which compiles with gcc 2.95.4:

Attrib Implicits(PadRcv *obj){
Attrib accum = 0;
PadRcv *padrcv;

if( !obj ) return 0;
char* (PadRcv::*pmfa)(char *) = &PadRcv::kbd;
void (PadRcv::*pmfb)() = &PadRcv::userclose;
if( obj->*pmfa != &PadRcv::kbd ) accum |= ACCEPT_KBD;
if( obj->*pmfb != &PadRcv::userclose ) accum |= USERCLOSE;
return accum;
}

With gcc 3.4.4, I get the following errors:

pad.C: In function `Attrib Implicits(PadRcv*)':
pad.C:27: error: invalid use of non-static member function
pad.C:28: error: invalid use of non-static member function
*** Error code 1

There is plenty of documentation on the net for pointers to member
functions and virtual functions but nothing seems to cover this
particular area.
Note that the first comparision is essentially

obj->*(&PadRcv::kbd) != &PadRcv::kbd

and one does not expect the two sides to have the same types since the
left hand side is in a sense dereferenced.

But it's worse: there's /no/ type in C++ for the result of "->*" and
".*". The only thing you can do with such a result is to use it as the
operand for the function call operator. I.e., apply (...).

One technical solution is to test for the presence of an interface
rather than presence of a virtual function, i.e. using dynamic_cast.

But in general a better approach is to design the base class so that it
doesn't need to know anything about its derived classes, and to not try
to be overly clever or do evil premature micro-optimization.

Now for details.

1. All uppercase for constants is a Java'ism.
Don't do it. Reserve all uppercase for macros.
2. More naming: "Implicits", "kbd" and "userclose" form a set of
names with no apparent naming convention.
3. Even more about names. PadRcv is just as silly as early assembly
language HLT, or Unix creat. Save one keystroke, for what?
4. The Attrib enumeration. In standard C++ you need to cast from
int to Attrib.
5. char* as argument is ungood. Use char const*. Or better,
std::string const&.
6. PadRcv* as argument is ungood. At least use PadRcv const*. But
better use PadRcv const&.
7. Kudos: your code caused MSVC 7.1 to ICE. ;-)

--
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?
Dec 20 '06 #5

P: n/a
I think I need to explain the rationale for needing to know
when the user derived class has overriden the virtual
function in the base class. The application is a window
on which there are various `layers'; a layer is a user-defined
object that is built on (derived from) a base layer class.

The application allows the user defined classes to supply
a keyboard handling function, and a function used to close,
the current object. If the user derived class has not supplied
either of these then a suitable message is printed. In the
case of a keyboard handler, the application will signal
whether the currently selected object on the screen will
accept input from the keyboard. The object in question
might be the whole layer, or just a selected line in the
layer.

I suppose this could be coded in a different way, but I
am working from very old C++ code. In the good old days
one could use function pointers, and it's this that I am
trying to port. As I pointed out, the code works in gcc 2.95.4.

The various replies, and my writing this response, make
me realise that I probably don't need to care about
whether the base class virtual function has been
overriden. The base class function prints something
suitable when invoked, and that is enough. If a user
class supplies a function, then it just does it's job.

By the way, upper-case for constants pre-dates Java by
a couple of decades. Dennis Ritchie's coding style can't
really be faulted. The code I'm working on is, well, vintage,
to say the least.

Many thanks for the responses.

Noel Hunt

Dec 20 '06 #6

P: n/a
* no*******@gmail.com:
>
By the way, upper-case for constants pre-dates Java by
a couple of decades.
Java got the convention from C, where it was used for macros, and of
course used for manifest constants defined as macros (C didn't
originally have 'const').

Since Java doesn't have a language-supported preprocessor only the
aspect of constantness survived.

And that is at odds with original purpose in C, to keep the "namespace"
of macros separate since macros don't respect scopes.

Dennis Ritchie's coding style can't really be faulted.
If what you mean is that, a couple of decades ago (we're talking 1970's
here) Dennis used all uppercase for manifest constants defined as
macros, then true, using all uppercase for macros can't really be
faulted, and that's what everyone should do -- see this group's FAQ as
well as Bjarne Stroustrup's FAQ. However, Dennis also used all
uppercase for typedef'ed names, and lowercase for functionlike macros.
And that can (really!) be faulted... From a modern point of view with
20-20 hindsight, that is. At that time the source code for a program
was considerably less than today, when included headers are counted, and
furthermore I suspect that Dennis had at least some degree of control
over the contents of those headers -- which we today don't have.

--
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?
Dec 20 '06 #7

This discussion thread is closed

Replies have been disabled for this discussion.