Topic: ambiguity rules in lookup have odd visibility
Author: gdr@cs.tamu.edu (Gabriel Dos Reis)
Date: Sun, 8 Aug 2004 23:42:26 GMT Raw View
On Fri, 6 Aug 2004, Ivan Godard wrote:
| class B1 {
| void Foo() {}
| };
| struct B2 {
| void Foo() {}
| };
| struct D : public B1, public B2 {
| void Bar() { Foo(); }
| };
| int main() {
| D d;
| return 0;
| }
|
| gets you:
|
|
| foo.cc: In member function `void D::Bar()':
| foo.cc:8: error: reference to `Foo' is ambiguous
| foo.cc:5: error: candidates are: void B2::Foo()
| foo.cc:2: error: void B1::Foo()
| foo.cc:8: error: `Foo' undeclared (first use this function)
| foo.cc:8: error: (Each undeclared identifier is reported only once for each
| function it appears in.)
|
|
|
|
| However, only one of the Foo's is visible.
How so?
| Apparently this is correct by the
| standard, but has the unfortunte consequence that the addition of a
| "private" function to a base class can cause previously correct derived
Access control is not visibility control. This is a FAQ, I think.
| classes to fail to compile. Beg pardon, but "private" should be private, and
| *nothing* you do in your private part should break something outside you.
In C++, private is private, i.e. access control, not visibility control.
| Could someone explain why invisible names count as ambiguous? (Please keep
They don't.
--
Gabriel Dos Reis
gdr@cs.tamu.edu
Texas A&M University -- Computer Science Department
301, Bright Building -- College Station, TX 77843-3112
---
[ 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://www.jamesd.demon.co.uk/csc/faq.html ]
Author: igodardA@TpacbellDO.Tnet ("Ivan Godard")
Date: Mon, 9 Aug 2004 00:43:52 GMT Raw View
"Jim Hyslop" <jhyslop@ieee.org> wrote in message
news:UyWQc.48922$Vm1.1159072@news20.bellglobal.com...
> > Could someone explain why invisible names count as ambiguous? (Please
keep
> > the explanation simple - I'm no C++ maven, just an interested user).
> Because the compiler first makes a list of candidate names, and only
> *after* it has chosen the appropriate name does it check the access
> privileges.
>
> Names are never invisible - just inaccessible. There's a big difference.
> Think of private names as being behind thick, bullet-proof glass - you
> can see them, but unless you have appropriate security clearances, you
> can't get at them.
>
> --
> Jim
Not quite what I asked :-) You explain how this is detected and reported,
but not *why* the standard was defined this way. I don't want to know how it
works - I knew that already. I'm looking for the rationale that led to it
working this way.
IMO, this behavior is a big fat information-hiding problem. I cannot see
where it provides any utility to the application; I can see where it would
be easy for the compiler to do it the other way (and yes, it would require a
backtracking resolver, but so what? Backtrack would be extremely rare.) And
it sure is lousy design when public-interface-preserving changes to the
private implementation can cause busted code in the users of the class.
Ivan
---
[ 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://www.jamesd.demon.co.uk/csc/faq.html ]
Author: brangdon@cix.co.uk (Dave Harris)
Date: Mon, 9 Aug 2004 15:34:52 GMT Raw View
igodardA@TpacbellDO.Tnet ("Ivan Godard") wrote (abridged):
> Not quite what I asked :-) You explain how this is detected and
> reported, but not *why* the standard was defined this way. I don't
> want to know how it works - I knew that already. I'm looking for
> the rationale that led to it working this way.
Such questions are addressed by Stroustrup's "Design and Evolution" book.
The answer in this case is "no reason". He says he doesn't remember
consciously designing it. From $2.10:
I do wonder if this aspect of the C++ definition is the result
of a genuine design decision. It could simply be the default
outcome of the preprocessor technology used to implement C
with Classes that didn't get reviewed when C++ was implemented
with more appropriate compiler technology.
You should also be aware that access control is orthogonal to virtualness.
In other words, private functions can override virtual base class ones,
and virtual private functions can be overridden by derived class ones. So
there are several ways in which private functions are not a pure
information-hiding solution.
class Base {
public:
virtual void method() = 0;
};
class Derived : public Base {
private:
void method() {}
};
Derived d;
Base &b = d;
b.method(); // Calls private Derived::method().
The author of Derived declared the method private and not virtual, but it
gets called anyway. This could be surprising if the author of Base adds
the virtual function without knowing the Derived method exists.
-- Dave Harris, Nottingham, UK
---
[ 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://www.jamesd.demon.co.uk/csc/faq.html ]
Author: dsp@bdal.de (=?ISO-8859-1?Q?=22Daniel_Kr=FCgler_=28ne_Spangenberg=29=22?=)
Date: Tue, 10 Aug 2004 05:53:55 GMT Raw View
Good morning Ivan Godard,
Ivan Godard schrieb:
>"Jim Hyslop" <jhyslop@ieee.org> wrote in message
>news:UyWQc.48922$Vm1.1159072@news20.bellglobal.com...
>
[snip]
>>Because the compiler first makes a list of candidate names, and only
>>*after* it has chosen the appropriate name does it check the access
>>privileges.
>>
>>Names are never invisible - just inaccessible. There's a big difference.
>>Think of private names as being behind thick, bullet-proof glass - you
>>can see them, but unless you have appropriate security clearances, you
>>can't get at them.
>>
>>--=20
>>Jim
>> =20
>>
>
>Not quite what I asked :-) You explain how this is detected and reported=
,
>but not *why* the standard was defined this way. I don't want to know ho=
w it
>works - I knew that already. I'm looking for the rationale that led to i=
t
>working this way.
>
>IMO, this behavior is a big fat information-hiding problem. I cannot see
>where it provides any utility to the application; I can see where it wou=
ld
>be easy for the compiler to do it the other way (and yes, it would requi=
re a
>backtracking resolver, but so what? Backtrack would be extremely rare.) =
And
>it sure is lousy design when public-interface-preserving changes to the
>private implementation can cause busted code in the users of the class.
>
One advantage of the access versus visibility rule is, that it allows=20
**implicit** usage of names, but
prevents them in situations where explicit usage is tried. Some examples=20
are:
- Overriding of **private** virtual functions.
- Member functions returning types with private names to take advantage=20
of some conversions/promotions,
but forbid explicit usage of those names, e.g.
template <typename T>
class MySmartPtr {
private:
typedef bool (MySmartPtr::* BoolReplacement)() const;
T* ptr_;
public:
operator BoolReplacement() const { return (ptr_ !=3D 0) ?=20
&MySmartPtr::operator! : 0; }
bool operator!() const { return ptr_ =3D=3D 0; }
};
void foo() {
MySmartPtr<int> p;
!p;
if (p); // Implicit usage of private BoolReplacement (conversion to boo=
l)
}
I hope those idioms give you some idea of the usefulness of the=20
accessibility rules.
Greetings from Bremen,
Daniel Kr=FCgler
---
[ 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://www.jamesd.demon.co.uk/csc/faq.html ]
Author: stephen.clamage@sun.com (Steve Clamage)
Date: Tue, 10 Aug 2004 06:11:12 GMT Raw View
Ivan Godard wrote:
>
> Not quite what I asked :-) You explain how this is detected and reported,
> but not *why* the standard was defined this way. I don't want to know how it
> works - I knew that already. I'm looking for the rationale that led to it
> working this way.
ARM first page of chapter 11 (page 239).
D&E section 2.10, pages 53-56.
>
> IMO, this behavior is a big fat information-hiding problem.
Access control is not intended to provide information hiding. It is
intended to prevent accidental access to non-public class members.
--
Steve Clamage, stephen.clamage@sun.com
---
[ 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://www.jamesd.demon.co.uk/csc/faq.html ]
Author: igodardA@TpacbellDO.Tnet ("Ivan Godard")
Date: Fri, 6 Aug 2004 18:24:44 GMT Raw View
class B1 {
void Foo() {}
};
struct B2 {
void Foo() {}
};
struct D : public B1, public B2 {
void Bar() { Foo(); }
};
int main() {
D d;
return 0;
}
gets you:
foo.cc: In member function `void D::Bar()':
foo.cc:8: error: reference to `Foo' is ambiguous
foo.cc:5: error: candidates are: void B2::Foo()
foo.cc:2: error: void B1::Foo()
foo.cc:8: error: `Foo' undeclared (first use this function)
foo.cc:8: error: (Each undeclared identifier is reported only once for each
function it appears in.)
However, only one of the Foo's is visible. Apparently this is correct by the
standard, but has the unfortunte consequence that the addition of a
"private" function to a base class can cause previously correct derived
classes to fail to compile. Beg pardon, but "private" should be private, and
*nothing* you do in your private part should break something outside you.
Could someone explain why invisible names count as ambiguous? (Please keep
the explanation simple - I'm no C++ maven, just an interested user).
Ivan
---
[ 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://www.jamesd.demon.co.uk/csc/faq.html ]
Author: jhyslop@ieee.org (Jim Hyslop)
Date: Sat, 7 Aug 2004 02:00:24 GMT Raw View
Ivan Godard wrote:
> class B1 {
> void Foo() {}
> };
> struct B2 {
> void Foo() {}
> };
> struct D : public B1, public B2 {
> void Bar() { Foo(); }
> };
> int main() {
> D d;
> return 0;
> }
[...]
> However, only one of the Foo's is visible. Apparently this is correct by the
> standard, but has the unfortunte consequence that the addition of a
> "private" function to a base class can cause previously correct derived
> classes to fail to compile. Beg pardon, but "private" should be private, and
> *nothing* you do in your private part should break something outside you.
>
> Could someone explain why invisible names count as ambiguous? (Please keep
> the explanation simple - I'm no C++ maven, just an interested user).
Because the compiler first makes a list of candidate names, and only
*after* it has chosen the appropriate name does it check the access
privileges.
Names are never invisible - just inaccessible. There's a big difference.
Think of private names as being behind thick, bullet-proof glass - you
can see them, but unless you have appropriate security clearances, you
can't get at them.
--
Jim
---
[ 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://www.jamesd.demon.co.uk/csc/faq.html ]