CodeGuru Home VC++ / MFC / C++ .NET / C# Visual Basic VB Forums Developer.com
Results 1 to 10 of 10
  1. #1
    Join Date
    Jun 2002
    Posts
    27

    question about Inheritance

    Specifically why does declaring a method in a derived class hide all methods of the same name in the base class?

    for instance why doesn't the following work:

    Code:
    class X {
      virtual void foo() { cout << "foo" << endl; };
    },
    
    class Y : public x {
      void foo( int x ) { cout << x << endl;
    };
    
    void Test() {
       Y yClass;
    
       y.foo( 2 ); // okay works
       y.foo( );    // Error.  X::foo() is hidden by Y::foo( int )
    }
    intuitively one would think that ALL methods from a base class are inherited by a derived class, unless the derived class overloads the method, in which case ALL methods except the overloaded method is inherited.

    does anyone know why the behavior is different?

    thanks

    Zameer

  2. #2
    Join Date
    Oct 2001
    Location
    Dublin, Eire
    Posts
    880
    If you want to use the function of X, you have to tell the compiler:
    ((X)y).foo();

    The why is probably to look in the object oriented concepts.
    Elrond
    A chess genius is a human being who focuses vast, little-understood mental gifts and labors on an ultimately trivial human enterprise.
    -- George Steiner

  3. #3
    Join Date
    Jun 2002
    Location
    Germany
    Posts
    1,557
    Elrond's suggestion to "cast" the instantiation of Y to type X will compile and run. However some programmers would consider this to be bad style.

    Your question actually touches on some critical aspects of the theory of object orientation, as Elrond suggested. Particularly interesting to you (although not apparent from your coding example) might be to study-up on polymorphism of pointers.

    Please note that your definitiion of void foo(int) in Y is, in fact, not an overwrite of virtual void foo(void) in X. In order to overwrite a function, both the return value as well as all input parameters must be identical.

    You also forgot to specify the access type of foo in each class definition. By failing to specify either public, protected, or private, the default is private. Y's inheritance of "public X" will only inherit the public member functions (of which there are none).

    Here is a corrected, full listing of your sample code.

    #include <iostream>
    #include <string>
    using namespace std;

    class X
    {
    public:
    virtual void foo() { cout << "foo" << endl; };
    };

    class Y : public X
    {
    public:
    void foo( int x ) { cout << x << endl; }
    };

    void Test()
    {
    Y y;

    y.foo( 2 ); // okay works
    ((X) y).foo( ); // "cast" y to type X
    }

    int main(int argc, char* argv[])
    {
    Test();
    return 1;
    }

    You're gonna go blind staring into that box all day.

  4. #4
    Join Date
    Mar 2002
    Location
    California
    Posts
    1,582
    An understanding of polymorphism does not explain why a derived class method hides a base class method with the same name but different signature. I find that somewhat annoying myself.

    I'm sure there is a specific reason why this is. Maybe it would be too difficult to handle by the compiler. Maybe it leads to an ambiguity. I'm not sure.

    Anybody have an explanation for this?

    Jeff

  5. #5
    Join Date
    Apr 1999
    Location
    Altrincham, England
    Posts
    4,470
    Consider the following:
    Code:
    struct B
    {
        void f(int);
    };
    
    struct D : B
    {
        void f(double);
        void g();
    };
    
    void D::g()
    {
        f(3);
    };
    Which f() should the compiler call? D::f() can be called by converting the integer actual argument, but B::f() is a closer match. What if f(int) was a global function, rather than a member of B?

    What the compiler does is this:

    1) it looks in the immediate scope (in the above case the scope of struct D) and makes a list of all the functions with the given name (f in this case). It takes no notice of accessibility or argument lists.

    2) If it finds no functions at all with that name it moves to the next enclosing scope (B in the example above), and repeats from 1) until it runs out of scopes.

    Also, note that "virtual" is a red herring in the original example.

    BTW the solution to the OP's problem is:
    Code:
    class X {
    public:
      virtual void foo() { cout << "foo" << endl; };
    };
    
    class Y : public x {
    public:
      void foo( int x ) { cout << x << endl;
    };
    
    void Test() {
       Y y;
    
       y.foo( 2 ); // okay works
       y.X::foo( );    // OK: specifies the scope
    }
    Explanation taken from "Exceptional C++" by Herb Sutter.
    Correct is better than fast. Simple is better than complex. Clear is better than cute. Safe is better than insecure.
    --
    Sutter and Alexandrescu, C++ Coding Standards

    Programs must be written for people to read, and only incidentally for machines to execute.

    --
    Harold Abelson and Gerald Jay Sussman

    The cheapest, fastest and most reliable components of a computer system are those that aren't there.
    -- Gordon Bell


  6. #6
    Join Date
    Mar 2002
    Location
    California
    Posts
    1,582
    "I can see clearly now, the rain is gone."

    Thanks Graham,

    Jeff

  7. #7
    Join Date
    Apr 1999
    Location
    Altrincham, England
    Posts
    4,470
    Thanks, Herb
    Correct is better than fast. Simple is better than complex. Clear is better than cute. Safe is better than insecure.
    --
    Sutter and Alexandrescu, C++ Coding Standards

    Programs must be written for people to read, and only incidentally for machines to execute.

    --
    Harold Abelson and Gerald Jay Sussman

    The cheapest, fastest and most reliable components of a computer system are those that aren't there.
    -- Gordon Bell


  8. #8
    Join Date
    Apr 1999
    Location
    Altrincham, England
    Posts
    4,470
    Here's a slightly more subtle one:
    Code:
    struct B
    {
        void f() const;
    };
    
    struct D : B
    {
        void f();
    };
    
    void g(const D& d)
    {
        d.f();    // Oops!
    }
    Correct is better than fast. Simple is better than complex. Clear is better than cute. Safe is better than insecure.
    --
    Sutter and Alexandrescu, C++ Coding Standards

    Programs must be written for people to read, and only incidentally for machines to execute.

    --
    Harold Abelson and Gerald Jay Sussman

    The cheapest, fastest and most reliable components of a computer system are those that aren't there.
    -- Gordon Bell


  9. #9
    Join Date
    Jun 2002
    Posts
    27

    thanks

    thanks Graham for the explanation...

    I guess my problem is that I think that when a class is inherited, it receives all the methods made available from the superclass. This, imho, should mean that one need not explicitly qualify where the method comes from.

    Maybe the comipler should search for an exact match amongst a list of all available functions.. but I can see that this too would create a lot of problems... hmmm maybe there is no exact solution..

    oh well..

  10. #10
    Join Date
    Apr 1999
    Location
    Altrincham, England
    Posts
    4,470
    Exactly - I think that, in this case, C++ implements the simplest rule: a given name hides all occurrences of that name in enclosing scopes. No caveats or conditions to remember.
    Correct is better than fast. Simple is better than complex. Clear is better than cute. Safe is better than insecure.
    --
    Sutter and Alexandrescu, C++ Coding Standards

    Programs must be written for people to read, and only incidentally for machines to execute.

    --
    Harold Abelson and Gerald Jay Sussman

    The cheapest, fastest and most reliable components of a computer system are those that aren't there.
    -- Gordon Bell


Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  





Click Here to Expand Forum to Full Width

Featured