Topic: Ambiguous conversion due to private ba


Author: clamage@Eng.Sun.COM (Steve Clamage)
Date: 1998/03/25
Raw View
In article 6DE8@central.beasys.com, David R Tribble <david.tribble@central.beasys.com> writes:
>jkanze@otelo.ibmmail.com wrote:
>> ...
>> But doesn't this sort of
>> defeat the purpose of private inheritance?  Private inheritance isn't
>> meant to represent an isA relationship.
>
>Huh?  Inheritance does mean an IsA relationship, private or
>otherwise.  Or does C++ grant some special meaning to private
>inheritance that doesn't apply to inheritance in general?

The IsA relationship means that you can use a Derived any place a
Base was expected. When you use private inheritance, that property
doesn't hold. In addition, private inheritance means the base class
interface is not usefully part of the derived class interface.
Example:
 class Base { public: void f(); ... };
 class Derived : private Base { ... };

 void foo(Base&);
 Base b;
 ...
 Derived d;
 foo(d); // error, no implicit conversion to Base&
 b = d;  // error, cannot assign Derived to Base
 d.f();  // error, f is not accessible

Thus, private inheritance fails any test of the IsA relationship.

---
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://reality.sgi.com/austern_mti/std-c++/faq.html              ]





Author: Valentin Bonnard <bonnardv@pratique.fr>
Date: 1998/03/26
Raw View
Steve Clamage wrote:

> Thus, private inheritance fails any test of the IsA relationship.

I would say that private inheritance is a private IsA relationship.
It means that only some trusted functions (member, friends) are
aware of the relationship, which may change in the future.

--

Valentin Bonnard                mailto:bonnardv@pratique.fr
info about C++/a propos du C++: http://pages.pratique.fr/~bonnardv/
---
[ 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: herbs@cntc.com (Herb Sutter)
Date: 1998/03/26
Raw View
Valentin Bonnard <bonnardv@pratique.fr> wrote:
>Steve Clamage wrote:
>> Thus, private inheritance fails any test of the IsA relationship.
>
>I would say that private inheritance is a private IsA relationship.
>It means that only some trusted functions (member, friends) are
>aware of the relationship, which may change in the future.

Even member functions can't use Base and Derived objects polymorphically.

Private inheritance is far closer to "has-a" membership than it is to
public inheritance. That's because private inheritance means
"is-implemented-in-terms-of" (not "is-a"), as does membership. Hence one
should always prefer membership unless private inheritance is really
necessary, which usually means: to access a protected member, to override
a virtual function, or to be constructed before base subobjects.

---
Herb Sutter (mailto:herbs@cntc.com)

Current Network Technologies Corp  2695 North Sheridan Way, Suite 150
www.cntc.com www.peerdirect.com    Mississauga Ontario Canada L5K 2N6
---
[ 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: Philippe Nobili <pnobili@imaginet.fr>
Date: 1998/03/27
Raw View
Valentin Bonnard wrote:
>
> Steve Clamage wrote:
>
> > Thus, private inheritance fails any test of the IsA relationship.
>
> I would say that private inheritance is a private IsA relationship.
> It means that only some trusted functions (member, friends) are
> aware of the relationship, which may change in the future.
>

It is just a matter of words, but words are important. Private 'IsA'
means that a class is implemented as another one (and that is, actually
what you say in your comments).
What you say(.i.e only some trusted functions are aware of the
relationship) exactly describes an 'is-implemented-in-terms-of'
relationship, definitely not an 'isA' relationship. 'isA' is, IMO,
either true or false, so that 'private isA' semantically makes no sense.

Just my point of view of course,
                 Philippe.
---
[ 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: Srinivas Vobilisetti <srinivas-v@usa.net>
Date: 1998/03/31
Raw View
Herb Sutter wrote:
>
> Valentin Bonnard <bonnardv@pratique.fr> wrote:
> >Steve Clamage wrote:
> >> Thus, private inheritance fails any test of the IsA relationship.
> >
> >I would say that private inheritance is a private IsA relationship.
> >It means that only some trusted functions (member, friends) are
> >aware of the relationship, which may change in the future.
>
> Even member functions can't use Base and Derived objects polymorphically.
>

Is this right?

I am of the opinion that the Base class and its immediate privately
derived Derived class member functions can implicitly convert a Derived
reference/pointer to a Base class reference/pointer. Also, as you said
in the paragraph below, "to override a virtual function", indicate the
Base class member functions can use Base and Derived objects
polymorphically.

>
> Private inheritance is far closer to "has-a" membership than it is to
> public inheritance. That's because private inheritance means
> "is-implemented-in-terms-of" (not "is-a"), as does membership. Hence one
> should always prefer membership unless private inheritance is really
> necessary, which usually means: to access a protected member, to override
> a virtual function, or to be constructed before base subobjects.
>

Srinivas
---
[ 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: clamage@Eng.Sun.COM (Steve Clamage)
Date: 1998/03/31
Raw View
In article 4826@usa.net, Srinivas Vobilisetti <srinivas-v@usa.net> writes:
>Herb Sutter wrote:
>>
>> Valentin Bonnard <bonnardv@pratique.fr> wrote:
>> >Steve Clamage wrote:
>> >> Thus, private inheritance fails any test of the IsA relationship.
>> >
>> >I would say that private inheritance is a private IsA relationship.
>> >It means that only some trusted functions (member, friends) are
>> >aware of the relationship, which may change in the future.
>>
>> Even member functions can't use Base and Derived objects polymorphically.
>>
>
>Is this right?
>
>I am of the opinion that the Base class and its immediate privately
>derived Derived class member functions can implicitly convert a Derived
>reference/pointer to a Base class reference/pointer.

That's correct, but the access applies only to immediate base classes.
Example:

class B { };

void f(B*);

class D : private B {
public:
        void g() { f(this); } // OK, convert D* to B*
};

class DD : public D {
public:
        void h() { f(this); } // error, no implicit conversion DD* to B*
};

You can use an explicit old-style cast to convert a DD* to a B*, but
I wouldn't call that polymorphism. You are not using a DD* as though
it were a B*, but are explicitly converting a DD* to a B*.

The "polymorphism" you do get is restricted to one level, so I don't
think it is useful to describe this situation as polymorphism or "IsA"
at all. If Valentin wants to invent a term "private IsA" to describe
this special case, I suppose he can do so, but I think that is more
misleading than helpful.

---
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://reality.sgi.com/austern_mti/std-c++/faq.html              ]





Author: clamage@Eng.Sun.COM (Steve Clamage)
Date: 1998/04/01
Raw View
In article 20E0@usa.net, Srinivas Vobilisetti <srinivas-v@usa.net> writes:
>Steve Clamage wrote:
>> Example:
>>
>> class B { };
>>
>> void f(B*);
>>
>> class D : private B {
>> public:
>>         void g() { f(this); } // OK, convert D* to B*
>> };
>>
>> class DD : public D {
>> public:
>>         void h() { f(this); } // error, no implicit conversion DD* to B*
>> };
>>
>> You can use an explicit old-style cast to convert a DD* to a B*, but
>> I wouldn't call that polymorphism. You are not using a DD* as though
>> it were a B*, but are explicitly converting a DD* to a B*.
>>
>> ....
>>
>
>Okay. I agree with you that DD* can not be implicitly assigned to B*.
>But can a virtual function in class B be overridden by the member
>function of class DD?

Yes. Inaccessible (e.g. private) names are still visible, and are
subject to all the usual rules about overriding and overloading.

>what should be the output of the following program? My HP compiler
>prints "Derived::virtf()\n" on the output.

That is correct. Class Derived inherits function g from ImmDerived,
a public function in a public base class, so it can be called from main.

Function g calls Base::f (the qualifier "Base::" is not necessary),
which is accessible from class ImmDerived. (The public members of a
private base class are accessible as private members of the derived
class, and "this" can be implicitly converted to a pointer to a private
immediate base class.)

Function f calls the virtual function virtf, whose final overrider
is in class Derived.

---
Steve Clamage, stephen.clamage@sun.com


>#include <iostream.h>
>
>class Base {
>public:
>   void f() { virtf(); }
>   virtual void virtf() { cout << "Base::virtf()\n"; }
>};
>
>class ImmDerived : private Base {
>public:
>   void g() { Base::f(); }
>   void virtf() { cout << "ImmDerived::virtf()\n"; }
>};
>
>class Derived : public ImmDerived {
>public:
>   void virtf() { cout << "Derived::virtf()\n"; }
>};
>
>int main()
>{
>   Derived d;
>   d.g();
>}
---
[ 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: Marc Girod <girod@stybba.ntc.nokia.com>
Date: 1998/04/01
Raw View
>>>>> "SC" == Steve Clamage <clamage@Eng.Sun.COM> writes:

SC> In article 4826@usa.net, Srinivas Vobilisetti <srinivas-v@usa.net> writes:
>> Herb Sutter wrote:
>>>
>>> Valentin Bonnard <bonnardv@pratique.fr> wrote:
>>> >Steve Clamage wrote:
>>> >> Thus, private inheritance fails any test of the IsA relationship.
>>> >
>>> >I would say that private inheritance is a private IsA relationship.
>>> >It means that only some trusted functions (member, friends) are
>>> >aware of the relationship, which may change in the future.
>>>
[...]
SC> That's correct, but the access applies only to immediate base classes.

You meant "to immediate derived classes", but you dropped friends.

SC> class B { };

SC> void f(B*);
SC> class D : private B {
    friend class E;
SC> public:
SC>         void g() { f(this); } // OK, convert D* to B*
SC> };

    class E {
    public:
            void h(D* d) { f(d); } // OK
    protected:
            B* base(D* d) { return d; } // OK
    };

SC> The "polymorphism" you do get is restricted to one level, so I don't
SC> think it is useful to describe this situation as polymorphism or "IsA"
SC> at all. If Valentin wants to invent a term "private IsA" to describe
SC> this special case, I suppose he can do so, but I think that is more
SC> misleading than helpful.

The polymorphism is scoped, that's all.
With the second member of E, it is even as deep as you want (in one
sense).

This is "interface dedication", extremely common and useful,
especially when applied to friend classes. Think at it as a
generalization of iterators to statefull accessors.

--
Marc Girod                Valimo 1/2         Voice:  +358-9-511 63331
Nokia Telecommunications  P.O. Box 315       Mobile: +358-40-569 7954
NWS/NMS/NMS for Data      00045 NOKIA Group  Fax:    +358-9-511 63310
                          Finland            marc.girod@ntc.nokia.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://reality.sgi.com/austern_mti/std-c++/faq.html              ]