Help me understand Overriding a virtual function

Discussion in 'C++' started by CoolPint, Jan 25, 2004.

  1. CoolPint

    CoolPint Guest

    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;
    }
    CoolPint, Jan 25, 2004
    #1
    1. Advertising

  2. "CoolPint" <> wrote in message
    news:...
    > 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.
    >


    Because if it did you could violate const correctness.

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


    Because with this you can't:
    A CPtr will return you a cont reference whether or not it is actually a Ptr.

    >
    > 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) { };


    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.

    > virtual const int & operator*() const
    > {
    > return *ptr;
    > }
    > virtual const char & vtest() { }


    returns what?

    > protected:
    > int * ptr;
    > };
    >
    > class Ptr: public CPtr {


    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.

    > public:
    > Ptr(int * a):CPtr(a) { };


    If you had CPtr(const int*) you would not now be able to initialize it with
    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


    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.

    > // Why?
    >
    > // cout << ++(*p) << endl;
    > }
    >
    > int main()
    > {
    > int i = 10;
    > Ptr pt(&i);
    > cout << ++(*pt) << endl;
    > fun(pt);
    >
    > return 0;
    > }
    Nick Hounsome, Jan 25, 2004
    #2
    1. Advertising

  3. CoolPint

    CoolPint Guest

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


    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.
    CoolPint, Jan 26, 2004
    #3
  4. CoolPint

    Ron Natalie Guest

    "CoolPint" <> wrote in message news:...

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


    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.

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


    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
    Ron Natalie, Jan 26, 2004
    #4
    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. dotnetprogram
    Replies:
    1
    Views:
    716
    Joey Powell
    Dec 27, 2003
  2. IK
    Replies:
    2
    Views:
    606
    hemraj
    Jul 23, 2004
  3. Achintya
    Replies:
    11
    Views:
    505
    vindhya
    Jul 25, 2005
  4. ctor
    Replies:
    13
    Views:
    584
    Howard
    Mar 9, 2006
  5. Peter Davis
    Replies:
    3
    Views:
    948
    Peter Davis
    Jul 25, 2012
Loading...

Share This Page