Topic: protected access restriction pains


Author: jodle@bix.com (jodle)
Date: 1995/05/14
Raw View
Atman Binstock (ajb@panix.com) wrote:

: 11.5.2 of the draft standard says:
:  A friend or a member function of a derived class can access a
:  protected nonstatic member of a base class.  Except when
:  forming a pointer to member (5.3.1), the  access must be
:  through a pointer to, reference to, or object of the derived
:  class itself (or any class derived from that class) (5.2.4).

: This seems to prevent certain styles of base class : derived class
: relationships where the derived classes define virtual functions that
: are not public members of the base class, but protected members used
: in implementation of both the base and derived classes.  That is,

This does indeed prevent certain kinds of relationships.  In particular,
it prevents you from doing this:

class Base { protected: int prot; };

class Derived: public Base { ... } d;

class Mine: public Base { void violator() {d.prot++;}};

Voila!  If the language were relaxed to allow the access you propose, I
could gain access to any protected data that is inherited by objects of
any class whatsoever.  The rule as it stands allows protected data access
up the inheritance graph, down the graph (narrowly), but not across the
graph.






Author: ajb@panix.com (Atman Binstock)
Date: 1995/05/07
Raw View
11.5.2 of the draft standard says:
 A friend or a member function of a derived class can access a
 protected nonstatic member of a base class.  Except when
 forming a pointer to member (5.3.1), the  access must be
 through a pointer to, reference to, or object of the derived
 class itself (or any class derived from that class) (5.2.4).

This seems to prevent certain styles of base class : derived class
relationships where the derived classes define virtual functions that
are not public members of the base class, but protected members used
in implementation of both the base and derived classes.  That is,
instead of allowing the derived classes to implement the (virtual)
members of the public interface of the base, the public base members
are non-virtual and the derived classes are restricted to an
abstraction defined by the protected (virtual) members of the base
class.  I find that this

My example is a class hierarchy with base class B and derived classes
D1..Dn.  For a concrete example imagine B is set<T>, D1 is
set_by_list<T>, D2 is set_by_tree<T>, etc and set() and get() are
replaced by something like has(T&) and to_each(functor<T&>&).

 class B {
 protected:
  //interface to derived classes
  struct state {
   //members of state depend on use of hierarchy
  };
  virtual void set(const state&) = 0;
  virtual state get() const = 0;
 public:
  B& operator=(const B& b) { set(b.get()); return *this; }

  friend bool operator==(const B& x, const B& y)
  { return x.get()==y.get(); }

  //etc
 };


 class D1 : public B {
 private:
  void set(const state&);
  state get() const;

 public:
  D1(const B& b);
  D1(const D1& d1) { set(d1.get()); }

  B& operator=(const B& b);
  D1& operator=(const D1& d1) { set(d1.get()); return *this; }
 };

We would like to define
  D1::D1(const B& b) { set(b.get()); }
and
  B& operator=(const B& b) { set(b.get()); return *this; }
but this the draft standard does not allow this, as the protected
access to B::get() is not by a reference to D1.

While we could define a protected:
 void B::assign(const B& b) { set(b.get()); }
so that
  D1::D1(const B& b) { assign(b); }
will work, there are other places where this will not work,
such as when we need to implement operations that are specific to
a derived class and use a base class argument:
 void D1::specialtoD1(const B& b) { state s = b.get(); //etc


Is there any chance of relaxing this rule?

Atman Binstock
ajb@panix.com