Topic: Derived class calling a protected base constructor


Author: Michiel Salters<Michiel.Salters@cmg.nl>
Date: Fri, 16 Mar 2001 11:03:09 GMT
Raw View
In article <MPG.150a3508ca298114989796@news.supernews.com>, Scott Meyers says...
>
>I know the rule about derived classes not being able to access protected
>members of base classes unless it's through a derived class object, and I
>thought I understood the motivations and ramifications of that design
>decision, but recently somebody asked me why a derived class member
>function can't call a protected base class constructor to create a local
>base class object.  In other words, they wanted to do this:
>
>  class Base {
>  protected:
>    Base(){}
>  };
>
>  class Derived: public Base {
>  public:
>    void foo() { Base b; }     // error!  can't call protected
>  };                           // constructor
>
>I am at a loss to explain why this is not allowed.  Can somebody please
>enlighten me so I can enlighten the person who asked me?
>
>Thanks,
>
>Scott

Scott, I'm not sure if you are questioning the design, or if you
can't find the rule. The rule is 11.5 [Protected member access], which
states that all protected access must be through a pointer to, reference
to or object of the class itself. Now, that's not the case here.
base::base() isn't accessed through derived::derived(), so it's
unaccessible.

Why this was done? Consistency, I guess. Making things protected means
the only way to get access to a base object name is via the containing
derived object. And in derived::foo() that base isn't contained in a
derived.

Regards,
Michiel Salters

---
[ 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.research.att.com/~austern/csc/faq.html                ]





Author: robertm@rojoma.com (Robert J. Macomber)
Date: Mon, 5 Mar 2001 19:54:14 GMT
Raw View
According to Scott Meyers  <smeyers@aristeia.com>:
> I know the rule about derived classes not being able to access protected
> members of base classes unless it's through a derived class object, and I
> thought I understood the motivations and ramifications of that design
> decision, but recently somebody asked me why a derived class member
> function can't call a protected base class constructor to create a local
> base class object.  In other words, they wanted to do this:

{snip example}

> I am at a loss to explain why this is not allowed.  Can somebody please
> enlighten me so I can enlighten the person who asked me?

Presumably, the only reason you'd want to do that is to prevent
someone from instantiating an object of that class without subclassing
it.  But in that case you can get the same effect by making the
constructor public and the destructor pure virtual, thus not requiring
an exception to the "protected" access rule (since, when the Derived
constructor wants to call the Base's, the object is not yet a
Derived - it's not even a Base).

The only other reasons I can think of to declare a non-copy
constructor non-public are for singletons or to force the use of a
factory of some sort, and generally you don't want to subclass in
those cases anyway.

The rule does seem to make protected constructors redundant.
--
Robert Macomber
robertm@rojoma.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.research.att.com/~austern/csc/faq.html                ]
[ Note that the FAQ URL has changed!  Please update your bookmarks.     ]





Author: "titi" <titi_@skynet.be>
Date: Mon, 5 Mar 2001 19:55:25 GMT
Raw View
> I know the rule about derived classes not being able to access protected
> members of base classes unless it's through a derived class object, and I
> thought I understood the motivations and ramifications of that design
> decision, but recently somebody asked me why a derived class member
> function can't call a protected base class constructor to create a local
> base class object.  In other words, they wanted to do this:
>
>   class Base {
>   protected:
>     Base(){}
>   };
>
>   class Derived: public Base {
>   public:
>     void foo() { Base b; }     // error!  can't call protected
>   };                           // constructor

[...]


Don't inline method foo() & try again. Does it give the same error then?

TiTi


---
[ 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.research.att.com/~austern/csc/faq.html                ]
[ Note that the FAQ URL has changed!  Please update your bookmarks.     ]





Author: "Michael Grimard" <michaelg@maxt.com>
Date: Mon, 5 Mar 2001 19:56:31 GMT
Raw View
AFAIK, base-class constructors are not inherited by derived classes, but
derived-class constructors can call base-class constructors.

In other words, only derived-class constructors can call base-class
contructors with the ":" notation. Member functions can't call base-class
constructors because there are not inherited.

HTH,
Michael

"Scott Meyers" <smeyers@aristeia.com> wrote in message
news:MPG.150a3508ca298114989796@news.supernews.com...
> I know the rule about derived classes not being able to access protected
> members of base classes unless it's through a derived class object, and I
> thought I understood the motivations and ramifications of that design
> decision, but recently somebody asked me why a derived class member
> function can't call a protected base class constructor to create a local
> base class object.  In other words, they wanted to do this:
>
>   class Base {
>   protected:
>     Base(){}
>   };
>
>   class Derived: public Base {
>   public:
>     void foo() { Base b; }     // error!  can't call protected
>   };                           // constructor
>
> I am at a loss to explain why this is not allowed.  Can somebody please
> enlighten me so I can enlighten the person who asked me?
>
> Thanks,
>
> Scott
>
> ---
> [ 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.research.att.com/~austern/csc/faq.html                ]
> [ Note that the FAQ URL has changed!  Please update your bookmarks.     ]
>

---
[ 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.research.att.com/~austern/csc/faq.html                ]
[ Note that the FAQ URL has changed!  Please update your bookmarks.     ]





Author: jpotter@falcon.lhup.edu (John Potter)
Date: Mon, 5 Mar 2001 21:33:19 GMT
Raw View
On Sun,  4 Mar 2001 18:23:24 GMT, Scott Meyers <smeyers@aristeia.com>
wrote:

> I know the rule about derived classes not being able to access protected
> members of base classes unless it's through a derived class object, and I
> thought I understood the motivations and ramifications of that design
> decision, but recently somebody asked me why a derived class member
> function can't call a protected base class constructor to create a local
> base class object.  In other words, they wanted to do this:
>
>   class Base {
>   protected:
>     Base(){}
>   };
>
>   class Derived: public Base {
>   public:
>     void foo() { Base b; }     // error!  can't call protected
>   };                           // constructor
>
> I am at a loss to explain why this is not allowed.  Can somebody please
> enlighten me so I can enlighten the person who asked me?

Seeing three non-answers, I will attempt one.

There is no reason, it's company policy.  :)

Seriously, a derived class member function has no rights to an isolated
base object's protected parts other than those of any global function or
member of any other class.  That is none.  It does have access to the
protected parts of the base subobject of objects of its own class.

Do you see any reason to rewrite the rule as a derived class has access
only to those protected parts of its own base except ...  How many
exceptions should there be and why?

In this little exmaple, of course, there is the silly bypass of using
the copy ctor.

   void foo () { Base b = Derived(); }

Now what would foo do with it?  It has no access to its protected parts.

John

---
[ 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.research.att.com/~austern/csc/faq.html                ]
[ Note that the FAQ URL has changed!  Please update your bookmarks.     ]





Author: Scott Meyers <smeyers@aristeia.com>
Date: Mon, 5 Mar 2001 22:21:17 GMT
Raw View
On Mon,  5 Mar 2001 21:33:19 GMT, John Potter wrote:
> In this little exmaple, of course, there is the silly bypass of using
> the copy ctor.
>
>    void foo () { Base b = Derived(); }
>
> Now what would foo do with it?  It has no access to its protected parts.

It could manipulate it via its public interface.  Presumably this is useful,
because Base is a concrete class.

Scott

---
[ 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.research.att.com/~austern/csc/faq.html                ]
[ Note that the FAQ URL has changed!  Please update your bookmarks.     ]





Author: "Victor Bazarov" <vAbazarov@dAnai.com>
Date: Mon, 5 Mar 2001 23:11:21 GMT
Raw View
"Scott Meyers" <smeyers@aristeia.com> wrote...
> On Mon,  5 Mar 2001 21:33:19 GMT, John Potter wrote:
> > In this little exmaple, of course, there is the silly bypass of
using
> > the copy ctor.
> >
> >    void foo () { Base b = Derived(); }
> >
> > Now what would foo do with it?  It has no access to its protected
parts.
>
> It could manipulate it via its public interface.  Presumably this is
useful,
> because Base is a concrete class.

If Base is a concrete class (designed to be used on its own), then
it has to have some legitimate ways for creating objects, no?  And
they are what you're supposed to use for instantiating an object...
Not the protected (from normal use) constructor... Or maybe I didn't
understand something...

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://www.research.att.com/~austern/csc/faq.html                ]
[ Note that the FAQ URL has changed!  Please update your bookmarks.     ]





Author: jpotter@falcon.lhup.edu (John Potter)
Date: Tue, 6 Mar 2001 00:02:36 GMT
Raw View
On Mon,  5 Mar 2001 22:21:17 GMT, Scott Meyers <smeyers@aristeia.com>
wrote:

> On Mon,  5 Mar 2001 21:33:19 GMT, John Potter wrote:
> > In this little exmaple, of course, there is the silly bypass of using
> > the copy ctor.
> >
> >    void foo () { Base b = Derived(); }
> >
> > Now what would foo do with it?  It has no access to its protected parts.
>
> It could manipulate it via its public interface.  Presumably this is
> useful, because Base is a concrete class.

But, you would never derive from a concrete class. <g>

I guess that I went too far.  The question is what can the member foo
of Derived do with it that a member of Unrelated or a namespace function
can't do?  Why should Derived::foo be able to default construct a Base
when no other function can?  Base was designed so that no default
constructed objects could be created.  Why it allows derived classes
to default construct their subobjects is beyond me, but the question
was about why the derived classes can't default construct
non-subobjects.  My answer is that it is consistent with all other
access rules and there is no reason to have special cases.  What did
I miss?

John

---
[ 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.research.att.com/~austern/csc/faq.html                ]
[ Note that the FAQ URL has changed!  Please update your bookmarks.     ]





Author: "Andrei Alexandrescu" <andrewalex@hotmail.com>
Date: Wed, 7 Mar 2001 19:48:07 GMT
Raw View
"Scott Meyers" <smeyers@aristeia.com> wrote in message
news:MPG.150a3508ca298114989796@news.supernews.com...
>   class Base {
>   protected:
>     Base(){}
>   };
>
>   class Derived: public Base {
>   public:
>     void foo() { Base b; }     // error!  can't call protected
>   };                           // constructor
>
> I am at a loss to explain why this is not allowed.  Can somebody please
> enlighten me so I can enlighten the person who asked me?

The rule is anyway very easy to circumvent:

class Derived: public Base {
public:
    void foo()
    {
        class Wyda : public Base {};
        Wyda b;
        ... use b ...
     }
};

A rule that you can circumvent can still be a good rule (see casts), but I
fail to find the conceptual backbone behind this protected stuff.


Andrei


---
[ 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.research.att.com/~austern/csc/faq.html                ]
[ Note that the FAQ URL has changed!  Please update your bookmarks.     ]





Author: Scott Meyers <smeyers@aristeia.com>
Date: Sun, 4 Mar 2001 18:23:24 GMT
Raw View
I know the rule about derived classes not being able to access protected
members of base classes unless it's through a derived class object, and I
thought I understood the motivations and ramifications of that design
decision, but recently somebody asked me why a derived class member
function can't call a protected base class constructor to create a local
base class object.  In other words, they wanted to do this:

  class Base {
  protected:
    Base(){}
  };

  class Derived: public Base {
  public:
    void foo() { Base b; }     // error!  can't call protected
  };                           // constructor

I am at a loss to explain why this is not allowed.  Can somebody please
enlighten me so I can enlighten the person who asked me?

Thanks,

Scott

---
[ 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.research.att.com/~austern/csc/faq.html                ]
[ Note that the FAQ URL has changed!  Please update your bookmarks.     ]