Help me understand Overriding a virtual function

Collapse
This topic is closed.
X
X
 
  • Time
  • Show
Clear All
new posts
  • CoolPint

    Help me understand Overriding a virtual function

    I read that the return type has to be exactly same for a virtual
    function to be overriden. While testing something, I discovered
    something I cannot understand.
    I cannot understand why the code below compiles.

    I see that it won't compile if I have "virtual char & vtest() { }" in
    Base class
    and have "virtual const char & vtest() { }" in Derived class.

    But it compiles if I have "virtual const char & vtest() { }" in Base
    class and have "virtual char & vtest() { }" in derived class.
    Why? What's going on?

    Similarly, operator*() functions compiles as written, but always
    returns const int & even I assign derived object to Base reference.
    Please have a look at comments on function fun() to see what I mean.

    Can anyone kindly explain why it compiles yet won't do dynamic
    binding?
    Thanks always (especially to you, Victor B.)

    #include <iostream>
    using std::cout;
    using std::endl;

    class CPtr {
    public:
    CPtr(int * a):ptr(a) { };
    virtual const int & operator*() const
    {
    return *ptr;
    }
    virtual const char & vtest() { }
    protected:
    int * ptr;
    };

    class Ptr: public CPtr {
    public:
    Ptr(int * a):CPtr(a) { };
    virtual int & operator*() const
    {
    return *ptr;
    }
    virtual char & ttest() { }
    };

    void fun(CPtr & p)
    {
    // I was hoping this would work since a Ptr object is passed and
    // dynamically it would bind to virtual int & operator*() const
    // But it binds to virtual const int & operator*() const at compile
    time
    // Why?

    // cout << ++(*p) << endl;
    }

    int main()
    {
    int i = 10;
    Ptr pt(&i);
    cout << ++(*pt) << endl;
    fun(pt);

    return 0;
    }
  • Nick Hounsome

    #2
    Re: Help me understand Overriding a virtual function


    "CoolPint" <coolpint@yahoo .co.uk> wrote in message
    news:159a5c32.0 401250338.d4557 ea@posting.goog le.com...[color=blue]
    > I read that the return type has to be exactly same for a virtual
    > function to be overriden. While testing something, I discovered
    > something I cannot understand.
    > I cannot understand why the code below compiles.
    >
    > I see that it won't compile if I have "virtual char & vtest() { }" in
    > Base class
    > and have "virtual const char & vtest() { }" in Derived class.
    >[/color]

    Because if it did you could violate const correctness.
    [color=blue]
    > But it compiles if I have "virtual const char & vtest() { }" in Base
    > class and have "virtual char & vtest() { }" in derived class.
    > Why? What's going on?[/color]

    Because with this you can't:
    A CPtr will return you a cont reference whether or not it is actually a Ptr.
    [color=blue]
    >
    > Similarly, operator*() functions compiles as written, but always
    > returns const int & even I assign derived object to Base reference.
    > Please have a look at comments on function fun() to see what I mean.
    >
    > Can anyone kindly explain why it compiles yet won't do dynamic
    > binding?
    > Thanks always (especially to you, Victor B.)
    >
    > #include <iostream>
    > using std::cout;
    > using std::endl;
    >
    > class CPtr {
    > public:
    > CPtr(int * a):ptr(a) { };[/color]

    This is the start of your misconceptions:
    If CPtr is a pointer to a const int then why doesn't it take one ine the
    constructor?
    Your CPtr cannot actually point to a constant integer!
    If you change to CPtr(const int*) the problems that you will then have with
    Ptr(int*) should show you
    why your design is flawed and why C++ works the way it does.
    [color=blue]
    > virtual const int & operator*() const
    > {
    > return *ptr;
    > }
    > virtual const char & vtest() { }[/color]

    returns what?
    [color=blue]
    > protected:
    > int * ptr;
    > };
    >
    > class Ptr: public CPtr {[/color]

    inheritance is not appropriate here.
    You are saying "Every Ptr IS-A CPtr"
    or "every pointer is a pointer to constant except that you can change it!"
    This is obviously nonsensical.
    [color=blue]
    > public:
    > Ptr(int * a):CPtr(a) { };[/color]

    If you had CPtr(const int*) you would not now be able to initialize it with
    a.
    [color=blue]
    > virtual int & operator*() const
    > {
    > return *ptr;
    > }
    > virtual char & ttest() { }
    > };
    >
    > void fun(CPtr & p)
    > {
    > // I was hoping this would work since a Ptr object is passed and
    > // dynamically it would bind to virtual int & operator*() const
    > // But it binds to virtual const int & operator*() const at compile
    > time[/color]

    No it doesn't - it binds to virtual int& operator*() (look at the asembler)
    BUT the the return type is treated as const int& because that is what it is
    in CPtr.

    C++ uses dynamic function calls but static type checking.
    Or to put it another way virtual function calls select functions at runtime
    NOT types.
    [color=blue]
    > // Why?
    >
    > // cout << ++(*p) << endl;
    > }
    >
    > int main()
    > {
    > int i = 10;
    > Ptr pt(&i);
    > cout << ++(*pt) << endl;
    > fun(pt);
    >
    > return 0;
    > }[/color]


    Comment

    • CoolPint

      #3
      Re: Help me understand Overriding a virtual function

      > No it doesn't - it binds to virtual int& operator*() (look at the asembler)[color=blue]
      > BUT the the return type is treated as const int& because that is what it is
      > in CPtr.
      >
      > C++ uses dynamic function calls but static type checking.
      > Or to put it another way virtual function calls select functions at runtime
      > NOT types.[/color]

      Does that mean return types of virtual functions do not take part in
      the resolving of dynamic binding?

      Thank you for your comments. The coding was made just to illustrate
      the points I am trying to ask in simple way without considering the
      design. What I really want to find out is the feature of the langauge
      and how it works and you kind of answered above there but it's not
      clear to me yet. Could you kindly elaborate a bit more?

      Books say the return type has to be exactly same when a virtual
      function is overriden but why doesn't compiler complain in the
      following case:

      Base member's return type : virtual const T &
      Derived member's return type : virtual T &

      They look different types to me but compiler doesn't complain. But
      compiler complains when the situation is reversed though.

      Does this mean I have successfully overridden the function for dynamic
      binding to work? If then, why calling the member function through base
      reference would return the base class member's return type?

      Thank you for your patience.

      Comment

      • Ron Natalie

        #4
        Re: Help me understand Overriding a virtual function


        "CoolPint" <coolpint@yahoo .co.uk> wrote in message news:159a5c32.0 401251829.4a116 b21@posting.goo gle.com...
        [color=blue]
        > Does that mean return types of virtual functions do not take part in
        > the resolving of dynamic binding?[/color]

        Correct. The important issue is name and parameter list. However,
        the return types of overriding functions are required to be same or one
        of the legal related types.
        [color=blue]
        > Books say the return type has to be exactly same when a virtual
        > function is overriden but why doesn't compiler complain in the
        > following case:[/color]

        Those books are wrong. The rule is relaxed in the case when:
        1. Both returns are pointers or references to classes
        2. The type of the base class function return is an unambiguous accessible base class
        of the return of the derived class function
        3. The CV-qualification is the same for the pointers, and the same or less qualfifed for
        the pointed/referred to derived object

        Comment

        Working...