Topic: overloading & inheritance


Author: Barry Margolin <barmar@genuity.net>
Date: 2000/09/15
Raw View
In article <8pnc6u$8g9$1@reader1.imaginet.fr>,
Hicham BOUHMADI <hicham@citeweb.net> wrote:
>I would like to know, why the standard is like this. Is there any reason
>behind this? (some C++ meta-rule that I don't know?)

Read "Design and Evolution of C++".

--
Barry Margolin, barmar@genuity.net
Genuity, Burlington, MA
*** DON'T SEND TECHNICAL QUESTIONS DIRECTLY TO ME, post them to newsgroups.
Please DON'T copy followups to me -- I'll assume it wasn't posted to the group.

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html              ]






Author: "Hicham BOUHMADI" <hicham@citeweb.net>
Date: 2000/09/15
Raw View
thanks William,
I got it now the "why" behind the fact that the scope of the derived class
is not a super-set of the scope of the base class.
thanks again.

Hicham BOUHMADI.
[...]
> Overloading could have been specified to work the way you
> thought it did, i.e., accumulating base and derived
> functions together.  The reason for choosing to treat base
> and derived classes as separate scopes was that it makes
> code easier to understand and less susceptible to being
> broken by changes.
>
> To see this, consider the case where you write a class in
> your code that is based on a class from a library.  Your
> class has a member function "f", and some of your code
> calls "f".
>
> Now you upgrade to version 2 of the library and as part of
> the enhancements, the vendor has added (perhaps in a remote
> base class) a function "f".  If things worked the way you
> thought, the new "f" in the vendor class could "hijack"
> some of the calls that previously went to your "f" (if it
> were a better overload match for the arguments you used),
> and your program wouldn't work any more.
>
> That may be a kind of far-fetched scenario, but it
> illustrates an important point -- locality of reference is
> important.  In general, you're going to know and understand
> your class better than one in a library written by someone
> else.  If you find a function or group of functions named
> "f" in your class, you shouldn't have to scan through the
> entire hierarchy to figure out what a call to "f" really
> means -- you can tell just by looking at your class by itself.
> That's why the "using A::f;" that has been mentioned
> several times in this thread is important -- it's a signal
> that you really _do_ need to look in base classes in order
> to figure out what a call to "f" means.
>
> --
> William M. Miller, wmm@fastdial.net
> Vignette Corporation (www.vignette.com)
>
>
> Sent via Deja.com http://www.deja.com/
> Before you buy.
>
> ---
> [ comp.std.c++ is moderated.  To submit articles, try just posting with ]
> [ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
> [              --- Please see the FAQ before posting. ---               ]
> [ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html              ]
>


---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html              ]






Author: Francis Glassborow <francis.glassborow@ntlworld.com>
Date: Wed, 13 Sep 2000 02:40:22 GMT
Raw View
In article <8plkg8$s71$1@reader1.imaginet.fr>, Hicham BOUHMADI
<hicham@citeweb.net> writes
>Is the following standard or not?

Well you need to think about the lack of access specifiers, but that is
not the reason you are asking.
>
>class A
>{
>    void f()
>    {}
>};
>
>class B : public A
>{
You need to write:
using A::f
to import the declarations of f found in A.
>    void f(int i)

You should use an anonymous parameter here as its value is not used in
the body of the code.
>    {}
>};
>
>int main ()
>{
>    B b;
>    b.f();

The above line should generate a diagnostic because there is no f()
visible in the scope of B, the f(int) hides the version in A.
>    return 0;
>}

Francis Glassborow      Association of C & C++ Users
64 Southfield Rd
Oxford OX4 1PA          +44(0)1865 246490
All opinions are mine and do not represent those of any organisation

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html              ]





Author: "Hicham BOUHMADI" <hicham@citeweb.net>
Date: 2000/09/13
Raw View
Thanks guys for your help :-)
Yesterday, I was in a hurry, so I made the mistake of substuting "class" to
"struct". Sorry...
I don't know exactly what the standard says but in general, when I am faced
to problems like the one I presented to you, I tried to think about a
"normal" behavior of the compiler. "Normal" in the context of some C++
"meta-rules". Most of the time, I get the correct / standard answer.
Sometimes, I fail to get it!
For the "overloading & inheritance" problem, I fails to get the standard
behavior... :-(
Here is my reasoning (if you find out a gap please point it to me):
* C++ supports function overloading
==> A function is defined in the compiler by its name + argument types +
scope
* if a struct B inherits from struct A, all A member functions are
accessible (can be called) through an instance of B. (I suppose there is no
private / protected section). This can be seen as B:: is an extention of
A::. B:: is a super-set of A::
* Specifying the scope is always allowed but it is necessary only when there
is an ambiguity

Now, when we take a look to the following exemple:
struct A { void f() {} };
struct B : public struct A { void f(int) {} };        file://Thanks Francis
for the annonymous parameter tip...
int main(){
B b;
b.f();}

* A::f is accessible through B
==> There is two functions f that are accessible f() & f(int). We are in the
same case, as if B has two functions f() & f(int)
* I called f without parameters. Due to the first meta-rule, there isn't any
ambiguity, the compiler can find out easily the "good" function.
*  If there is no ambiguity, there is no need to clarify the scope!
==> it should compiles!!

I would like to know, why the standard is like this. Is there any reason
behind this? (some C++ meta-rule that I don't know?)

Hicham BOUHMADI                hicham@citeweb.net


---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html              ]






Author: Francis Glassborow <francis.glassborow@ntlworld.com>
Date: 2000/09/13
Raw View
In article <8pnc6u$8g9$1@reader1.imaginet.fr>, Hicham BOUHMADI
<hicham@citeweb.net> writes
>* A::f is accessible through B

NO, it isn't the faint) in the derived class hides it. Overloading rules
prohibit a search of a base class if the name has already been found in
the derived class. That is why you must include

using A::f

in the derived class.


Francis Glassborow      Association of C & C++ Users
64 Southfield Rd
Oxford OX4 1PA          +44(0)1865 246490
All opinions are mine and do not represent those of any organisation

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html              ]






Author: wmm@fastdial.net
Date: 2000/09/14
Raw View
In article <8pnc6u$8g9$1@reader1.imaginet.fr>,
  "Hicham BOUHMADI" <hicham@citeweb.net> wrote:
> Here is my reasoning (if you find out a gap please point it to me):
> * C++ supports function overloading
> ==> A function is defined in the compiler by its name + argument
types +
> scope
> * if a struct B inherits from struct A, all A member functions are
> accessible (can be called) through an instance of B. (I suppose there
is no
> private / protected section). This can be seen as B:: is an extention
of
> A::. B:: is a super-set of A::
> * Specifying the scope is always allowed but it is necessary only
when there
> is an ambiguity
>
> Now, when we take a look to the following exemple:
> struct A { void f() {} };
> struct B : public struct A { void f(int) {} };        file://Thanks
Francis
> for the annonymous parameter tip...
> int main(){
> B b;
> b.f();}
>
> * A::f is accessible through B
> ==> There is two functions f that are accessible f() & f(int). We are
in the
> same case, as if B has two functions f() & f(int)
> * I called f without parameters. Due to the first meta-rule, there
isn't any
> ambiguity, the compiler can find out easily the "good" function.
> *  If there is no ambiguity, there is no need to clarify the scope!
> ==> it should compiles!!
>
> I would like to know, why the standard is like this. Is there any
reason
> behind this? (some C++ meta-rule that I don't know?)

The point that you are missing in your analysis is that
overloading is done only _within_ a scope, not by
_combining_ scopes, and a derived class is a _separate_
scope from its base.  Since you have an entity named "f"
in the class "B", it _hides_ the entity named "f" that
was inherited from class "A".  Think of it in terms of
data members:

    struct X { int i; };
    struct Y: X { int i; };

    void f(Y y) {
        y.i = 5;        // Y::i, because X::i is hidden
        y.X::i = 10;    // access hidden member
    }

You can also think of it as working like nested lexical
scopes:

    void f();           // outer declaration
    void g() {
        void f(int);    // inner declaration
        f();            // ill-formed -- outer "f" is
                        // hidden, not overloaded
        ::f();          // access hidden declaration
    }

Here, the outer declaration corresponds to the one in the
base class and the inner declaration is like the one in
the derived class.  You can't write "f()" because the only
visible (non-hidden) declaration of "f" requires an
argument.

Overloading could have been specified to work the way you
thought it did, i.e., accumulating base and derived
functions together.  The reason for choosing to treat base
and derived classes as separate scopes was that it makes
code easier to understand and less susceptible to being
broken by changes.

To see this, consider the case where you write a class in
your code that is based on a class from a library.  Your
class has a member function "f", and some of your code
calls "f".

Now you upgrade to version 2 of the library and as part of
the enhancements, the vendor has added (perhaps in a remote
base class) a function "f".  If things worked the way you
thought, the new "f" in the vendor class could "hijack"
some of the calls that previously went to your "f" (if it
were a better overload match for the arguments you used),
and your program wouldn't work any more.

That may be a kind of far-fetched scenario, but it
illustrates an important point -- locality of reference is
important.  In general, you're going to know and understand
your class better than one in a library written by someone
else.  If you find a function or group of functions named
"f" in your class, you shouldn't have to scan through the
entire hierarchy to figure out what a call to "f" really
means -- you can tell just by looking at your class by itself.
That's why the "using A::f;" that has been mentioned
several times in this thread is important -- it's a signal
that you really _do_ need to look in base classes in order
to figure out what a call to "f" means.

--
William M. Miller, wmm@fastdial.net
Vignette Corporation (www.vignette.com)


Sent via Deja.com http://www.deja.com/
Before you buy.

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html              ]






Author: James Kuyper <kuyper@wizard.net>
Date: 2000/09/14
Raw View
Hicham BOUHMADI wrote:
...
> struct A { void f() {} };
> struct B : public struct A { void f(int) {} };        file://Thanks Francis
> for the annonymous parameter tip...
> int main(){
> B b;
> b.f();}
>
> * A::f is accessible through B

A function of a given name in a derived class hides ALL functions of the
same name inherited from the base class(es), regardless of signature.
You can override this hiding by the use of 'using' declarations.

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html              ]






Author: "Hicham BOUHMADI" <hicham@citeweb.net>
Date: Tue, 12 Sep 2000 16:56:57 GMT
Raw View
Is the following standard or not?

class A
{
    void f()
    {}
};

class B : public A
{
    void f(int i)
    {}
};

int main ()
{
    B b;
    b.f();
    return 0;
}


---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html              ]





Author: "Victor Bazarov" <vAbazarov@dAnai.com>
Date: Tue, 12 Sep 2000 17:28:11 GMT
Raw View
"Hicham BOUHMADI" <hicham@citeweb.net> wrote...
> Is the following standard or not?
>
> class A
> {
>     void f()
>     {}
> };
>
> class B : public A
> {
>     void f(int i)
>     {}
> };
>
> int main ()
> {
>     B b;
>     b.f();

This should produce an error message like "inaccessible private
member".  And if you replace the 'class' with 'struct' in the
definitions above, the message should change to something like
"not enough arguments in function call".

>     return 0;
> }

To use both f(int) and f() functions with an object of struct B,
declare B using A::f like this:

struct B : A
{
    using A::f;
    void...
};

Victor
--
Please remove capital A's from my address when replying by mail



---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html              ]





Author: Francis Glassborow <francis.glassborow@ntlworld.com>
Date: Tue, 12 Sep 2000 18:31:55 GMT
Raw View
In article <8plogl$b1v$1@bob.news.rcn.net>, Victor Bazarov
<vAbazarov@dAnai.com> writes
>This should produce an error message like "inaccessible private member".
>And if you replace the 'class' with 'struct' in the definitions above,
>the message should change to something like "not enough arguments in
>function call".

No, it should always generate the latter style of diagnostic as access
is not checked till after overload resolution.


Francis Glassborow      Association of C & C++ Users
64 Southfield Rd
Oxford OX4 1PA          +44(0)1865 246490
All opinions are mine and do not represent those of any organisation

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html              ]