Hi all,
I am wondering why the language allows a programmer to inherit from a
base class that contains virtual functions (either pure virtual or
non-pure virtual functions) and override them with a different access
specifier (i.e. private vs. public).
For example:
class Base {
private:
virtual void fn() =0;
};
class Derived : public Base {
public:
void fn();
};
is valid code. However, given a base class pointer, fn cannot be called:
Base* bp = new Derived;
bp->fn(); // Illegal - fn is private
Derived* dp = new Derived;
dp->fn(); // OK
Why does the language allow this?
When would I need to use this?
How often is it done in practice?
What other ramifications are there other than the base-class pointer
issue illustrated above?
Thanks,
Matt.
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
0
|
|
|
|
Reply
|
Matthew
|
9/1/2004 9:33:04 PM |
|
"Matthew Peavy" <mje@mpeavy.com> wrote in message
news:InnZc.28$De5.56414@news.uswest.net...
> Hi all,
>
> I am wondering why the language allows a programmer to inherit from a
> base class that contains virtual functions (either pure virtual or
> non-pure virtual functions) and override them with a different access
> specifier (i.e. private vs. public).
>
> For example:
>
> class Base {
> private:
> virtual void fn() =0;
> };
>
> class Derived : public Base {
> public:
> void fn();
> };
>
>
> is valid code. However, given a base class pointer, fn cannot be called:
>
>
> Base* bp = new Derived;
> bp->fn(); // Illegal - fn is private
>
> Derived* dp = new Derived;
> dp->fn(); // OK
>
>
> Why does the language allow this?
> When would I need to use this?
> How often is it done in practice?
> What other ramifications are there other than the base-class pointer
> issue illustrated above?
If a class is intended to be used as a base class, declaring its destructor
as private virtual, will make the call to the destructor of the derived
class
object when it is destroyed. Otherwise the behavior is undefined. Defining
it as pure virtual makes sense for abstract classes, because abstract
classes
are intended to be used as base classes. This issue is discussed in detail
in: Effective C++, Item14 (ISBN 0-201-92488-9)
Regards,
Soheil
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
0
|
|
|
|
Reply
|
Soheil
|
9/2/2004 12:02:45 PM
|
|
Matthew Peavy <mje@mpeavy.com> wrote in message
news:<InnZc.28$De5.56414@news.uswest.net>...
> I am wondering why the language allows a programmer to inherit from a
> base class that contains virtual functions (either pure virtual or
> non-pure virtual functions) and override them with a different access
> specifier (i.e. private vs. public).
Probably because there didn't seem to be any overwhelming reason to
forbid it. When in doubt, trust the programmer.
In practice, there are definitly times when the derived class might want
to relax the access, i.e. make a private function public. I can't think
of any cases where the reverse is useful, but I don't see what benefits
would be had by banning it.
> For example:
> class Base {
> private:
> virtual void fn() =0;
> };
> class Derived : public Base {
> public:
> void fn();
> };
> is valid code. However, given a base class pointer, fn cannot be
> called:
> Base* bp = new Derived;
> bp->fn(); // Illegal - fn is private
> Derived* dp = new Derived;
> dp->fn(); // OK
> Why does the language allow this?
Because there's no reason to forbid it. In this case, it could easily
be useful.
> When would I need to use this?
When the derived class extends the interface provided by the base
class. Would you get upset if the derived class added another new
function with a different name to the public interface?
> How often is it done in practice?
I don't know. Most of the time, I imagine, when the derived class
extends the base class, it will be by means of new functions; I would
guess that it is pretty rare for an existing private virtual function in
the base class to correspond exactly to the extension wanted.
> What other ramifications are there other than the base-class pointer
> issue illustrated above?
What sort of ramifications are you looking for? The derived class
defines a new interface, which extends the base class interface. That
seems a perfectly normal use of derivation to me.
--
James Kanze GABI Software http://www.gabi-soft.fr
Conseils en informatique orient�e objet/
Beratung in objektorientierter Datenverarbeitung
9 place S�mard, 78210 St.-Cyr-l'�cole, France, +33 (0)1 30 23 00 34
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
0
|
|
|
|
Reply
|
kanze
|
9/3/2004 2:07:39 AM
|
|
Matthew Peavy wrote:
> I am wondering why the language allows a programmer to inherit from a
> base class that contains virtual functions (either pure virtual or
> non-pure virtual functions) and override them with a different access
> specifier (i.e. private vs. public).
>
> For example:
>
> class Base {
> private:
> virtual void fn() =0;
> };
>
> class Derived : public Base {
> public:
> void fn();
> };
>
> is valid code. However, given a base class pointer, fn cannot be called:
>
> Base* bp = new Derived;
> bp->fn(); // Illegal - fn is private
>
> Derived* dp = new Derived;
> dp->fn(); // OK
>
> Why does the language allow this?
Why should the language prohibit it? The behavior is well defined, and
it doesn't let you get any special access to the private parts of a
class. In C++, overriding and accessibility are considered to be
orthoganal issues, and the behavior you are seeing is just the fallout
of that decision. There should be a good reason for a language to
prohibit a well-defined behavior, and simply being useless is not a good
enough reason.
> When would I need to use this?
Probably never. At most very rarely.
> How often is it done in practice?
Very rarely.
> What other ramifications are there other than the base-class pointer
> issue illustrated above?
None that I can think of. But because I haven't seen any real code like
this, I haven't tried to find all the ramifications. If you encounter
code like this, just remember that accessibility checking of member
function calls is done based on the static type of the object.
--
David Olsen
qg4h9ykc5m@yahoo.com
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
0
|
|
|
|
Reply
|
David
|
9/3/2004 12:33:40 PM
|
|
"Soheil Evoghli" <soheil@awb.us> wrote in message
news:<KquZc.542655$Gx4.93313@bgtnsc04-news.ops.worldnet.att.net>...
> If a class is intended to be used as a base class, declaring its
> destructor as private virtual, will make the call to the destructor of
> the derived class object when it is destroyed.
Declaring the destructor private, whether virtual or not, will make it
impossible to derive from the class (and impossible to declare a local
or static instance of the class). I'm pretty sure that the private
wasn't meant in your statement. (Since you cannot derive from the
class, there's no point in ever delaring a virtual destructor private.)
Typically, if a class is meant to be a base class, it will have either a
public virtual destructor, or a protected destructor.
> Otherwise the behavior is undefined. Defining it as pure virtual
> makes sense for abstract classes, because abstract classes are
> intended to be used as base classes.
On the other hand, if the class is already abstract, there's no point in
declaring the destructor pure virtual as well.
> This issue is discussed in detail in: Effective C++, Item14 (ISBN
> 0-201-92488-9)
I'm pretty sure that the destructors in Scott's code are public, not
private.
--
James Kanze GABI Software http://www.gabi-soft.fr
Conseils en informatique orient�e objet/
Beratung in objektorientierter Datenverarbeitung
9 place S�mard, 78210 St.-Cyr-l'�cole, France, +33 (0)1 30 23 00 34
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
0
|
|
|
|
Reply
|
kanze
|
9/4/2004 1:48:59 AM
|
|
Matthew Peavy <mje@mpeavy.com> wrote in message news:<InnZc.28$De5.56414@news.uswest.net>...
> Hi all,
>
> I am wondering why the language allows a programmer to inherit from a
> base class that contains virtual functions (either pure virtual or
> non-pure virtual functions) and override them with a different access
> specifier (i.e. private vs. public).
[snip]
> Why does the language allow this?
> When would I need to use this?
> How often is it done in practice?
> What other ramifications are there other than the base-class pointer
> issue illustrated above?
Herb Sutter has a couple of excellent articles highlighting the idioms
that this behavior allows:
"Virtually Yours", (with Jim Hyslop) C/C++ Users Journal, 18(12),
December 2000
http://www.cuj.com/documents/s=8000/cujcexp1812hyslop/
"Virtuality", C/C++ Users Journal, 19(9), September 2001
http://www.gotw.ca/publications/mill18.htm
In these articles, he illustrates a variation of Template Method which
he now refers to as the Nonvirtual Interface pattern, which is a more
specific instance of Template Method in this case. "Virtuality" is
updated as Item 18 in his new "Exceptional C++ Style"
(http://www.gotw.ca/publications/xc++s.htm), which makes explicit use
of the term "Nonvirtual Interface".
Mike
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
0
|
|
|
|
Reply
|
mbland
|
9/4/2004 2:17:34 AM
|
|
mje@mpeavy.com (Matthew Peavy) wrote (abridged):
> I am wondering why the language allows a programmer to inherit from a
> base class that contains virtual functions (either pure virtual or
> non-pure virtual functions) and override them with a different access
> specifier (i.e. private vs. public).
>
> For example:
>
> class Base {
> private:
> virtual void fn() =0;
> };
>
> class Derived : public Base {
> public:
> void fn();
> };
>
>
> is valid code. However, given a base class pointer, fn cannot be called:
It can be called by members and friends of Base. That is presumably why it
is declared in Base - so Base members can call it. It's virtual so that
Derived can override it. It's private because clients of Base don't need
to call it.
If Derived wants to make it public, what harm is done? It doesn't break
Liskov substitutability.
The controversial case is the other way around: public in Base and private
in Derived. This is permitted, too.
-- Dave Harris, Nottingham, UK
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
0
|
|
|
|
Reply
|
brangdon
|
9/4/2004 2:23:22 AM
|
|
brangdon@cix.co.uk (Dave Harris) wrote in message news:<memo.20040903183404.2092B@brangdon.m>...
>
> It can be called by members and friends of Base. That is presumably why it
> is declared in Base - so Base members can call it. It's virtual so that
> Derived can override it. It's private because clients of Base don't need
> to call it.
>
> If Derived wants to make it public, what harm is done? It doesn't break
> Liskov substitutability.
>
> The controversial case is the other way around: public in Base and private
> in Derived. This is permitted, too.
I don't see why this is controversial. Where a family of objects is
derived from an abstract Base, it is usual (Liskov substitution and
all that) for Base to be the 'important' class in the sense that the
concrete types do not have direct clients, but rather are accessed
throughout the system via the Base interface. The concrete derived
types may be constructed by a factory and that may be the first, last,
and only place in the system that is/should be concerned with the
concrete type. If this is the case then I do not see any problem in
re-declaring the functions of the implemented interface as private to
reinforce the fact that they should not be called directly on the
concrete objects.
Another effect is to discourage derivation from the concrete object.
(I think it was one of Scott Meyer's recommendations to avoid deriving
from 'leaf' classes.)
--
Ian
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
0
|
|
|
|
Reply
|
ian_news66
|
9/5/2004 11:36:41 AM
|
|
ian_news66@yahoo.co.uk (Ian) writes:
|> brangdon@cix.co.uk (Dave Harris) wrote in message news:<memo.20040903183404.2092B@brangdon.m>...
|> > It can be called by members and friends of Base. That is
|> > presumably why it is declared in Base - so Base members can call
|> > it. It's virtual so that Derived can override it. It's private
|> > because clients of Base don't need to call it.
|> > If Derived wants to make it public, what harm is done? It doesn't
|> > break Liskov substitutability.
|> > The controversial case is the other way around: public in Base
|> > and private in Derived. This is permitted, too.
|> I don't see why this is controversial. Where a family of objects is
|> derived from an abstract Base, it is usual (Liskov substitution and
|> all that) for Base to be the 'important' class in the sense that the
|> concrete types do not have direct clients, but rather are accessed
|> throughout the system via the Base interface. The concrete derived
|> types may be constructed by a factory and that may be the first,
|> last, and only place in the system that is/should be concerned with
|> the concrete type. If this is the case then I do not see any problem
|> in re-declaring the functions of the implemented interface as
|> private to reinforce the fact that they should not be called
|> directly on the concrete objects.
If there are no pointers to the derived type after the factory method,
it really doesn't matter whether the function is private or not. If,
however, for any reason, I obtain a pointer to the derived type, the LSP
says that any function I could have called on the Base type can be
called on the Derived type. Increasing protection violates the LSP.
--
James Kanze
Conseils en informatique orient�e objet/
Beratung in objektorientierter Datenverarbeitung
9 place S�mard, 78210 St.-Cyr-l'�cole, France +33 (0)1 30 23 00 34
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
0
|
|
|
|
Reply
|
James
|
9/6/2004 11:16:27 AM
|
|
mbland@acm.org (Mike Bland) wrote in message news:<b808d7c1.0409030632.79c45436@posting.google.com>...
> Matthew Peavy <mje@mpeavy.com> wrote in message news:<InnZc.28$De5.56414@news.uswest.net>...
> > Hi all,
> >
> > I am wondering why the language allows a programmer to inherit from a
> > base class that contains virtual functions (either pure virtual or
> > non-pure virtual functions) and override them with a different access
> > specifier (i.e. private vs. public).
>
> [snip]
>
> > Why does the language allow this?
> > When would I need to use this?
> > How often is it done in practice?
> > What other ramifications are there other than the base-class pointer
> > issue illustrated above?
>
> Herb Sutter has a couple of excellent articles highlighting the idioms
> that this behavior allows:
>
> "Virtually Yours", (with Jim Hyslop) C/C++ Users Journal, 18(12),
> December 2000
> http://www.cuj.com/documents/s=8000/cujcexp1812hyslop/
>
> "Virtuality", C/C++ Users Journal, 19(9), September 2001
> http://www.gotw.ca/publications/mill18.htm
>
> In these articles, he illustrates a variation of Template Method which
> he now refers to as the Nonvirtual Interface pattern, which is a more
> specific instance of Template Method in this case. "Virtuality" is
> updated as Item 18 in his new "Exceptional C++ Style"
> (http://www.gotw.ca/publications/xc++s.htm), which makes explicit use
> of the term "Nonvirtual Interface".
>
I think NVI (Non-Virtual Interface Idiom) is neither of access
promotion case nor access demotion case for from a base class to a
derived class.
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
0
|
|
|
|
Reply
|
hosoda
|
9/7/2004 10:35:44 AM
|
|
hosoda@jtec.or.jp (Tokyo Tomy) wrote in message news:<49c1da0b.0409062058.616797c4@posting.google.com>...
> mbland@acm.org (Mike Bland) wrote in message news:<b808d7c1.0409030632.79c45436@posting.google.com>...
> > In these articles, he illustrates a variation of Template Method which
> > he now refers to as the Nonvirtual Interface pattern, which is a more
> > specific instance of Template Method in this case. "Virtuality" is
> > updated as Item 18 in his new "Exceptional C++ Style"
> > (http://www.gotw.ca/publications/xc++s.htm), which makes explicit use
> > of the term "Nonvirtual Interface".
> >
> I think NVI (Non-Virtual Interface Idiom) is neither of access
> promotion case nor access demotion case for from a base class to a
> derived class.
Right, but in the articles, in the course of explaining NVI, Herb does
point out how virtual function access specifiers can change between
base and derived classes and why you'd want to do such a thing.
Mike
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
0
|
|
|
|
Reply
|
mbland
|
9/7/2004 11:14:10 PM
|
|
|
10 Replies
465 Views
(page loaded in 0.091 seconds)
Similiar Articles: Changing access specifiers during inheritance - comp.lang.c++ ...Hi all, I am wondering why the language allows a programmer to inherit from a base class that contains virtual functions (either pure virtual or no... multiple inheritance usage - comp.soft-sys.matlabAlternately, use the method I used for system-tray messages, which has ... multiple inheritance usage - comp.soft-sys.matlab Enum type inside a class (matlab <-> java ... Bridge patterns and protected inheritance? - comp.lang.c++ ...Changing access specifiers during inheritance - comp.lang.c++ ..... Method which > he now refers to as the Nonvirtual Interface pattern ... A default access level is ... How to Change a language??? - comp.cad.solidworksYahoo mail language change - comp.mail.misc How can I change the language of my yahoo mail access ... How to Change The Language Used to Read Websites | eHow.com If you live ... Yahoo mail language change - comp.mail.miscChanging access specifiers during inheritance - comp.lang.c++ ... How to Change a language??? - comp.cad.solidworks Yahoo mail Spanish to English? - comp.mail.misc How can ... Change interface language of Yahoo Mail - comp.mail.misc ...Changing access specifiers during inheritance - comp.lang.c++ ... When the derived class extends the interface provided by the base class. ... Yahoo mail Spanish to ... Yahoo mail Spanish to English? - comp.mail.miscChanging access specifiers during inheritance - comp.lang.c++ ... How to Change a language??? - comp.cad.solidworks Yahoo mail Spanish to English? - comp.mail.misc How can ... Animated gif stops after the form is submitted - comp.lang ...Hi folks, In IE, the animated gif will stop after the form is submitted. I even put the animated gif in the iframe, still no luck. Would anybody kn... Best design for my classes to avoid code duplication? - comp.lang ...Inheritance was invented for a different thing, and would ... with this approach is that the common code needs access ... During the time after C++ got MI, but before it got ... Lost Memory in RAM card - comp.sys.hp48I have a 128K HP RAM card which became "confused" during ... of either the 48SX or the 48GX, but only lets you access ... that > the calculator should be turned on while changing ... Changing access specifiers during inheritance - comp.lang.c++ ...Hi all, I am wondering why the language allows a programmer to inherit from a base class that contains virtual functions (either pure virtual or no... C++ Inheritance Access Specifiers (previously: Types of C++ ...... to change the title of the article and the initial summary to something more accurate. In C++ there are three inheritance access specifiers: ... mode during Inheritance ... 7/24/2012 7:39:19 PM
|