Topic: Accessing a base class' protected member


Author: belvis@pacbell.net (Bob Bell)
Date: Fri, 23 Jan 2004 23:21:28 +0000 (UTC)
Raw View
fp@fpx.de (Frank Pilhofer) wrote in message news:<slrnc0uim9.md.fp@ariel.fpx.de>...
> Hi,
>
> I am wondering about the "additional check" that applies to accessing
> protected members (11.5, p. 182), which restricts access to only pointers
> of the same type. This does not allow access of a protected member through
> a pointer to the base type. I.e., this means that the following is invalid:
>
> class B {
> protected:
>   int i;
> };
>
> class D : public B {
>   void foo (D*, B *);
> };
>
> void D::foo (D * thed, B * theb)
> {
>   i = 1;        // ok, implicit access through this
>   this->i = 1;  // ok, access through this
>   thed->i = 1;  // ok, pointer of the same type
>   theb->i = 1;  // not allowed
> }
>
> Yet, as the developer of a derived class, I am perfectly aware of the
> semantics of the base interface, so I can't see why access in the last
> case should be denied.

Let's assume that theb points to a C:

class C : public B {
//...
};

Because i is a protected member of B, that means a C object can
manipulate it however it wants. In effect, class C is allowed to use i
in a manner consistent with C's invariants. To allow another unrelated
function (in this case D::foo()) to manipulate it would therefore
violate C's encapsulation.

> My case in point is a chain of std::streambuf buffers, where one
> streambuf enforces a protocol over another: say, one of them implements
> a TCP stream, and the other implements HTTP. I had the idea that the
> "upper-level" streambuf would access the "lower-level" streambuf's
> buffer and use it as its own. Like a "write through", to get closer
> to zero-copy.
>
> However, because the other streambuf's gptr() functions et al are
> protected, this additional check disallows access.
>
> Of course the "upper-level" streambuf doesn't need to buffer and can
> just forward reads and writes, but it's still more overhead, especially
> if you keep on stacking streambufs.
>
> Could you please explain the rationale for this behavior? There is a
> full section for it, so there's probably a good reason. Is my idea bad
> design?

Well, I don't know if I'd do it the way you're doing it. For one
thing, both the TCP stream and the HTTP stream would be seen as having
a buffer. What would it mean to derive from the HTTP stream and write
directly to its buffer?

It seems to me that a better model for a class implementing HTTP would
have member functions that reflect the messages that are part of HTTP,
like get and put; the abstraction of HTTP doesn't seem to fit
streambuf. However, TCP/IP probably makes more sense as a derived
class of streambuf, since the abstractions as similar enough.

Then you could have the HTTP class read and write to a iostream, which
could be a TCP/IP stream, or could be some other iostream.

Hope that helps,

Bob

---
[ 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: fp@fpx.de (Frank Pilhofer)
Date: Thu, 22 Jan 2004 07:03:27 +0000 (UTC)
Raw View
Hi,

I am wondering about the "additional check" that applies to accessing
protected members (11.5, p. 182), which restricts access to only pointers
of the same type. This does not allow access of a protected member through
a pointer to the base type. I.e., this means that the following is invalid:

class B {
protected:
  int i;
};

class D : public B {
  void foo (D*, B *);
};

void D::foo (D * thed, B * theb)
{
  i = 1;        // ok, implicit access through this
  this->i = 1;  // ok, access through this
  thed->i = 1;  // ok, pointer of the same type
  theb->i = 1;  // not allowed
}

Yet, as the developer of a derived class, I am perfectly aware of the
semantics of the base interface, so I can't see why access in the last
case should be denied.

My case in point is a chain of std::streambuf buffers, where one
streambuf enforces a protocol over another: say, one of them implements
a TCP stream, and the other implements HTTP. I had the idea that the
"upper-level" streambuf would access the "lower-level" streambuf's
buffer and use it as its own. Like a "write through", to get closer
to zero-copy.

However, because the other streambuf's gptr() functions et al are
protected, this additional check disallows access.

Of course the "upper-level" streambuf doesn't need to buffer and can
just forward reads and writes, but it's still more overhead, especially
if you keep on stacking streambufs.

Could you please explain the rationale for this behavior? There is a
full section for it, so there's probably a good reason. Is my idea bad
design?

Thanks,
Frank

--
Frank Pilhofer  ...........................................  fp@fpx.de
It's not just the ups and downs that make life difficult, it's the
jerks. - Alfred E. Neuman

---
[ 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: hyrosen@mail.com (Hyman Rosen)
Date: Fri, 23 Jan 2004 06:12:26 +0000 (UTC)
Raw View
Frank Pilhofer wrote:
 > I can't see why access in the last case should be denied.

If it were permitted, then protected might as well be public:

     struct ForMyKids { protected: void f(); };
     struct GoodKid : ForMyKids { };
     struct Cuckoo : ForMyKids  { static void betray(ForMyKids &k) { k.f(); } }

     int main() { GoodKid k; Cuckoo::betray(k); }

---
[ 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: Fri, 23 Jan 2004 06:12:51 +0000 (UTC)
Raw View
The reason for the restriction is given in the ARM, section 11.5 (pages
253-255), along with a real-world example that prompted this rule.

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

Frank Pilhofer wrote:
> Hi,
>
> I am wondering about the "additional check" that applies to accessing
> protected members (11.5, p. 182), which restricts access to only pointers
> of the same type. This does not allow access of a protected member through
> a pointer to the base type. I.e., this means that the following is invalid:
>
> class B {
> protected:
>   int i;
> };
>
> class D : public B {
>   void foo (D*, B *);
> };
>
> void D::foo (D * thed, B * theb)
> {
>   i = 1;        // ok, implicit access through this
>   this->i = 1;  // ok, access through this
>   thed->i = 1;  // ok, pointer of the same type
>   theb->i = 1;  // not allowed
> }
>
> Yet, as the developer of a derived class, I am perfectly aware of the
> semantics of the base interface, so I can't see why access in the last
> case should be denied.
>
> My case in point is a chain of std::streambuf buffers, where one
> streambuf enforces a protocol over another: say, one of them implements
> a TCP stream, and the other implements HTTP. I had the idea that the
> "upper-level" streambuf would access the "lower-level" streambuf's
> buffer and use it as its own. Like a "write through", to get closer
> to zero-copy.
>
> However, because the other streambuf's gptr() functions et al are
> protected, this additional check disallows access.
>
> Of course the "upper-level" streambuf doesn't need to buffer and can
> just forward reads and writes, but it's still more overhead, especially
> if you keep on stacking streambufs.
>
> Could you please explain the rationale for this behavior? There is a
> full section for it, so there's probably a good reason. Is my idea bad
> design?
>

---
[ 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                       ]