Simultaneously overriding multiple member functions

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

    #1

    Simultaneously overriding multiple member functions

    #include <iostream>
    using namespace std;

    struct Base
    {
    virtual int foo () {return 1;}
    virtual int foo (int i) {return 2;}

    virtual ~Base () {}
    };

    struct Derived : Base
    {
    virtual int foo (int i = 3) {return i;}
    };

    int main ()
    {
    Derived* d1 = new Derived;
    Base* d2 = new Derived;
    cout << d1->foo() << " " << d1->foo(4) << endl;
    cout << d2->foo() << " " << d2->foo(4) << endl;
    delete d2;
    delete d1;
    }

    I was a little bit surprised to see the output of this short program:

    3 4
    1 4

    Specifically, the '1' was unexpected. What rule (or rules) make it so
    that d2->foo() calls Base::foo() rather than Derived::foo() with a
    default argument?

    Thanks,
    Mark
  • AnalogFile

    #2
    Re: Simultaneously overriding multiple member functions

    Mark P wrote:[color=blue]
    > #include <iostream>
    > using namespace std;
    >
    > struct Base
    > {
    > virtual int foo () {return 1;}
    > virtual int foo (int i) {return 2;}
    >
    > virtual ~Base () {}
    > };
    >
    > struct Derived : Base
    > {
    > virtual int foo (int i = 3) {return i;}[/color]

    This overrides Base::foo(int) and also defines a default argument for
    it. The default argument will be in effect only if you call the method
    from a reference to Derived.
    It also hides Base::foo(). It does NOT override it. Base::foo(), being
    hidden, cannot be called from a Derived object, unless you explicitelly
    qualify the call.
    [color=blue]
    > };
    >
    > int main ()
    > {
    > Derived* d1 = new Derived;
    > Base* d2 = new Derived;
    > cout << d1->foo() << " " << d1->foo(4) << endl;[/color]

    You are calling throu a Derived. The only visible member is
    Derived::foo(in t). It has a default argument. Both calls are to that
    method, the first one will use the default.
    [color=blue]
    > cout << d2->foo() << " " << d2->foo(4) << endl;[/color]

    You are calling throu a Base (with dynamic type Derived). Both methods
    are visible. The default value of Derived::foo(in t) is not in effect.
    Base::foo() is not overridden. Base::foo(int) is overridden.

    The first call is to Base::foo(), which is not overridden.

    The only visible member is Derived::foo(in t). It has a default argument.
    Both calls are to that method, the first one will use the default.
    [color=blue]
    > I was a little bit surprised to see the output of this short program:
    >
    > 3 4
    > 1 4[/color]

    We aren't ;-)
    [color=blue]
    >
    > Specifically, the '1' was unexpected. What rule (or rules) make it so
    > that d2->foo() calls Base::foo() rather than Derived::foo() with a
    > default argument?[/color]

    See above.
    Also consider (note: I'm writing straight in the news client, forgive
    any typing error):

    /** ****** **/

    struct Base {
    virtual void foo();
    virtual void foo(int);
    };
    struct Derived {
    virtual foo();
    };
    .....
    Derived d;
    d.foo(2); // ERROR


    the Base::foo(int) is hidden. If you want to call it you need:

    d.Base::foo(2);



    /** ****** **/

    struct Base {
    virtual void foo(int);
    };
    struct Derived {
    virtual foo(int i=5);
    };
    .....
    Base *p=new Derived;
    p->foo(); // ERROR

    the default is in effect for a call through Derived, but we are calling
    through Base. And this is somewhat obvious: what would it be if you also
    had:

    struct Descendant: public Derived {
    virtual foo(int i=7);
    };

    Comment

    • AnalogFile

      #3
      Re: Simultaneously overriding multiple member functions

      AnalogFile wrote:

      Sorry. Some cut&paste mixup.
      The previous post is incorrect. This part:
      [color=blue][color=green]
      >> cout << d2->foo() << " " << d2->foo(4) << endl;[/color]
      >
      > You are calling throu a Base (with dynamic type Derived). Both methods
      > are visible. The default value of Derived::foo(in t) is not in effect.
      > Base::foo() is not overridden. Base::foo(int) is overridden.
      >
      > The first call is to Base::foo(), which is not overridden.
      >
      > The only visible member is Derived::foo(in t). It has a default argument.
      > Both calls are to that method, the first one will use the default.
      >[/color]

      Should have been:

      [color=blue]
      > cout << d2->foo() << " " << d2->foo(4) << endl;[/color]

      You are calling through a Base (with dynamic type Derived). Both methods
      are visible. The default value of Derived::foo(in t) is not in effect.
      Base::foo() is not overridden. Base::foo(int) is overridden.

      The first call is to Base::foo(), which is not overridden and is
      therefore executed.
      The second call is to Base::foo(int) which is overridden by
      Derived::foo(in t), the latter is therefore executed.

      Comment

      • Mark P

        #4
        Re: Simultaneously overriding multiple member functions

        AnalogFile wrote:[color=blue]
        > Mark P wrote:[color=green]
        >> #include <iostream>
        >> using namespace std;
        >>
        >> struct Base
        >> {
        >> virtual int foo () {return 1;}
        >> virtual int foo (int i) {return 2;}
        >>
        >> virtual ~Base () {}
        >> };
        >>
        >> struct Derived : Base
        >> {
        >> virtual int foo (int i = 3) {return i;}[/color]
        >
        > This overrides Base::foo(int) and also defines a default argument for
        > it. The default argument will be in effect only if you call the method
        > from a reference to Derived.
        > It also hides Base::foo(). It does NOT override it. Base::foo(), being
        > hidden, cannot be called from a Derived object, unless you explicitelly
        > qualify the call.
        >[color=green]
        >> };
        >>
        >> int main ()
        >> {
        >> Derived* d1 = new Derived;
        >> Base* d2 = new Derived;
        >> cout << d1->foo() << " " << d1->foo(4) << endl;[/color]
        >
        > You are calling throu a Derived. The only visible member is
        > Derived::foo(in t). It has a default argument. Both calls are to that
        > method, the first one will use the default.
        >[color=green]
        >> cout << d2->foo() << " " << d2->foo(4) << endl;[/color]
        >
        > You are calling throu a Base (with dynamic type Derived). Both methods
        > are visible. The default value of Derived::foo(in t) is not in effect.
        > Base::foo() is not overridden. Base::foo(int) is overridden.
        >
        > The first call is to Base::foo(), which is not overridden.
        >
        > The only visible member is Derived::foo(in t). It has a default argument.
        > Both calls are to that method, the first one will use the default.
        >[color=green]
        >> I was a little bit surprised to see the output of this short program:
        >>
        >> 3 4
        >> 1 4[/color]
        >
        > We aren't ;-)
        >[color=green]
        >>
        >> Specifically, the '1' was unexpected. What rule (or rules) make it so
        >> that d2->foo() calls Base::foo() rather than Derived::foo() with a
        >> default argument?[/color]
        >
        > See above.
        > Also consider (note: I'm writing straight in the news client, forgive
        > any typing error):
        >
        > /** ****** **/
        >
        > struct Base {
        > virtual void foo();
        > virtual void foo(int);
        > };
        > struct Derived {
        > virtual foo();
        > };
        > ....
        > Derived d;
        > d.foo(2); // ERROR
        >
        >
        > the Base::foo(int) is hidden. If you want to call it you need:
        >
        > d.Base::foo(2);
        >
        >
        >
        > /** ****** **/
        >
        > struct Base {
        > virtual void foo(int);
        > };
        > struct Derived {
        > virtual foo(int i=5);
        > };
        > ....
        > Base *p=new Derived;
        > p->foo(); // ERROR
        >
        > the default is in effect for a call through Derived, but we are calling
        > through Base. And this is somewhat obvious: what would it be if you also
        > had:
        >
        > struct Descendant: public Derived {
        > virtual foo(int i=7);
        > };[/color]

        Very clear and helpful! Thanks a lot.

        Mark

        Comment

        Working...