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

Discussion in 'C++' started by noel.hunt@gmail.com, Dec 20, 2006.

  1. Guest

    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, 2006
    #1
    1. Advertising

  2. Steve Pope Guest

    <> 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?


    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
     
    Steve Pope, Dec 20, 2006
    #2
    1. Advertising

  3. On Dec 20, 7:38 am, 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
     
    =?iso-8859-1?q?Erik_Wikstr=F6m?=, Dec 20, 2006
    #3
  4. Salt_Peter Guest

    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.
     
    Salt_Peter, Dec 20, 2006
    #4
  5. * :
    > 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?
     
    Alf P. Steinbach, Dec 20, 2006
    #5
  6. Guest

    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, 2006
    #6
  7. * :
    >
    > 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?
     
    Alf P. Steinbach, Dec 20, 2006
    #7
    1. Advertising

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

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Makis Papapanagiotou

    Re: return types for virtual overriden functions

    Makis Papapanagiotou, Jul 31, 2003, in forum: C++
    Replies:
    2
    Views:
    322
    Victor Bazarov
    Jul 31, 2003
  2. Howard
    Replies:
    2
    Views:
    395
    Karl Heinz Buchegger
    Jul 31, 2003
  3. tomek
    Replies:
    2
    Views:
    710
    Andrey Tarasevich
    Dec 1, 2003
  4. tomek
    Replies:
    3
    Views:
    793
    David Fisher
    Nov 30, 2003
  5. Chunhui Han
    Replies:
    2
    Views:
    533
Loading...

Share This Page