Override public virtual Functions with private Functions?

C

Chris Gordon-Smith

Hello All

I have a base class called Action_Request, and a set of classes
corresponding to different kinds of Action_Request, each of which inherits
from Action_Request. Eg:-

class Add_Molecule_Req: public Action_Request{
// ......
};

I manipulate the various derived classes polymorphically through
Action_Requests's public interface, using its virtual functions.
Currently the overriding functions in the derived classes (including the
destructor, which overrides Action_Request's virtual destructor), are
declared public.

My program compiles if I make them private, and doing this would seem to
have the advantage that these functions must then always be invoked
polymorphically through Action_Request's public interface, which is what I
want.

My questions are:-

i) Is overriding public virtual functions with private functions good
practice?
ii) Are there any disadvantages?

Chris Gordon-Smith
www.simsoup.info
 
D

dizzy

Chris said:
My questions are:-

i) Is overriding public virtual functions with private functions good
practice?
ii) Are there any disadvantages?

In general you should separate interface (the public API the base class
provides) from configurability (the overriding feature). This is also
called the Template Method Pattern and is described in detail here:
http://www.gotw.ca/publications/mill18.htm
 
C

Chris Gordon-Smith

Daniel said:
I tend to follow the guideline, "make it private if you can, public if
you must." I consider such code "good practice".
Sounds sensible to me. What I hadn't appreciated (because I hadn't really
thought about it), is that private methods in derived class can override
public methods in the base.
The only disadvantage is that someone with a object of some
ActionRequest sub-class will have to up-cast the object.

In my case that is not a problem, because manipulation should only ever take
place through the base. If I ever attempt manipulation through a derived
class pointer I will get a compiler error. Upcasting would be possible, but
would be working against my basic design principle.

Chris Gordon-Smith
www.simsoup.info
 
J

James Kanze

I have a base class called Action_Request, and a set of
classes corresponding to different kinds of Action_Request,
each of which inherits from Action_Request. Eg:-
class Add_Molecule_Req: public Action_Request{
// ......
};
I manipulate the various derived classes polymorphically
through Action_Requests's public interface, using its virtual
functions. Currently the overriding functions in the derived
classes (including the destructor, which overrides
Action_Request's virtual destructor), are declared public.
My program compiles if I make them private, and doing this
would seem to have the advantage that these functions must
then always be invoked polymorphically through
Action_Request's public interface, which is what I want.
My questions are:-
i) Is overriding public virtual functions with private functions good
practice?
ii) Are there any disadvantages?

It's more a style issue than anything else. My personal
guidelines are to never change the access of a virtual function
in the derived class, since I find it confusing that the same
function has different access depending on the static type used
to access it. The disadvantage that I see is that someone
working on the derived class, later, may think that the
functions in question cannot be called from outside the class.
And of course, making them private does sort of violate the LSP:
if I have a Derived, I can't call them, although I could if I
had a Base.
 
A

anon

dizzy said:
In general you should separate interface (the public API the base class
provides) from configurability (the overriding feature). This is also
called the Template Method Pattern and is described in detail here:
http://www.gotw.ca/publications/mill18.htm

Interesting article. It says that in some cases the destructor should be
made protected. I have never thought about it before, and it made me
wonder why would anyone make the destructor private or protected.
So, the question is what are uses of such destructor?
 
B

Barry

anon said:
Interesting article. It says that in some cases the destructor should be
made protected. I have never thought about it before, and it made me
wonder why would anyone make the destructor private or protected.
So, the question is what are uses of such destructor?

Considering a class wrapping only static function as helper or factory
function, we should make the dtor private not to allow any instance.

We can also make the dtor private and with a static function "destroy"
to allow instance created only by new (no stack allocation)

making the dtor protected, then child class publicly/protectedly
derived from from still has access to it. at this time, you can never
delete a pointer to the base class.
 
J

James Kanze

dizzy wrote:
Interesting article. It says that in some cases the destructor
should be made protected. I have never thought about it
before, and it made me wonder why would anyone make the
destructor private or protected. So, the question is what are
uses of such destructor?

If the destructor is protected or private, you cannot allocate
static or automatic instances of the type, and you cannot call
delete on pointers to the type. In client code; you can still
do pretty much anything you want in the implementation of the
class itself.

Private destructors might make sense if the class itself
controls its lifetime: the only time it should be destructed is
in response to some external event (in which case, it does a
delete this). This is often the case for entity classes, for
example.

Protected destructors make a lot of sense for classes which are
designed to be used as base classes (and only as base classes),
but which don't have a virtual destructor. Classes like
std::iterator<>, for example.
 
C

Chris Gordon-Smith

James said:
It's more a style issue than anything else. My personal
guidelines are to never change the access of a virtual function
in the derived class, since I find it confusing that the same
function has different access depending on the static type used
to access it. The disadvantage that I see is that someone
working on the derived class, later, may think that the
functions in question cannot be called from outside the class.
And of course, making them private does sort of violate the LSP:
if I have a Derived, I can't call them, although I could if I
had a Base.

Thanks for this - interesting. As I understand it, the Liskov Substitution
Principle (LSP) is about maintaining the "is a" relationship between the
derived class and the base class. What I am trying to do is to use the base
class to provide a common interface to a set of classes that can be used
polymorphically. Does the LSP apply in this case?

Chris Gordon-Smith
www.simsoup.info
 
C

Chris Gordon-Smith

Daniel said:
Note that James said it "sort of" violated the LSP, in actual fact it
doesn't violate the LSP at all. Although this isn't a mark against it,
it is also not a mark for it. :)

Something to think about. If some user of the derived class does up-cast
and then call the base class member-function, would that necessarily be
an error?

I don't think I would call it an error, but it would not be how I intend the
class to be used. The code that uses my class is now more complex, because
sometimes it uses the base class interface directly, and sometimes uses it
by up-casting.

Chris Gordon-Smith
www.simsoup.info
 
D

Daniel T.

Daniel T. wrote:

I don't think I would call it an error, but it would not be how I intend the
class to be used. The code that uses my class is now more complex, because
sometimes it uses the base class interface directly, and sometimes uses it
by up-casting.

That latter comment is a strong reason to go ahead and make the member-
function public in the derived class.
 
C

Chris Gordon-Smith

Daniel said:
That latter comment is a strong reason to go ahead and make the member-
function public in the derived class.

Not really. The fact that up-casting would be necessary is a strong
indication that the class is not intended to be used in this way. By only
using the base class interface we keep the calling code simple and avoid
any up-casting.

Chris Gordon-Smith
www.simsoup.info
 
D

Daniel Pitts

Chris said:
Not really. The fact that up-casting would be necessary is a strong
indication that the class is not intended to be used in this way. By only
using the base class interface we keep the calling code simple and avoid
any up-casting.

Chris Gordon-Smith
www.simsoup.info
The real question is, why don't you want people to call
Derived->baseMethod()? What harm comes from it, and what benefit comes
from preventing it?

Polymorphic methods work the same whether you have a pointer/reference
to a Base or Derived class. That's *why* they are virtual.
 
C

Chris Gordon-Smith

Daniel said:
The real question is, why don't you want people to call
Derived->baseMethod()? What harm comes from it, and what benefit comes
from preventing it?

The benefit is standardisation and simplification. The base and its derived
classes are designed to be used polymorphically in a standard way through
the base class's interface. Using the interfaces of the various derived
classes would go against this and increase overall complexity and introduce
the possibility of error. If the classes are used in the way intended,
there is no need to call using the derived class's interface.
Polymorphic methods work the same whether you have a pointer/reference
to a Base or Derived class. That's *why* they are virtual.

Chris Gordon-Smith
www.simsoup.info
 
J

James Kanze

Note that James said it "sort of" violated the LSP, in actual fact it
doesn't violate the LSP at all. Although this isn't a mark against it,
it is also not a mark for it. :)

It depends on how you consider the LSP. It most definitely
violates the usual understanding of LSP. Typically, in C++,
this violation won't be visible, since client code expecting a
Base will take a Base* or a Base&, and won't see the fact that
the functions are private in the derived class. It might become
visible, however, in the presense of templates.
 
J

James Kanze

The benefit is standardisation and simplification. The base
and its derived classes are designed to be used
polymorphically in a standard way through the base class's
interface.

One of the characteristics of inheritance is normally that the
Base class' interface is part of the derived class' interface,
i.e. if I have something like:

struct Base { void f() ; } ;
struct Derived : Base { void g() ; } ;

then the "interface" defined by Derived includes both f() and
g().
 
C

Chris Gordon-Smith

James said:
One of the characteristics of inheritance is normally that the
Base class' interface is part of the derived class' interface,
i.e. if I have something like:

struct Base { void f() ; } ;
struct Derived : Base { void g() ; } ;

then the "interface" defined by Derived includes both f() and
g().

True enough. In the case of my Action_Requests however, I don't want to use
the derived class' interface. I always want to call polymorphically through
the base interface.

Chris Gordon-Smith
www.simsoup.info
 
J

James Kanze

James Kanze wrote:

[...]
True enough. In the case of my Action_Requests however, I
don't want to use the derived class' interface. I always want
to call polymorphically through the base interface.

In that case, you probably also want a factory which returns the
actual instances, so that the client code doesn't even know that
the derived classes exist. (And of course, in that case,
whether the virtual functions are public or are private in the
derived class really doesn't matter, since the client code
doesn't have access to the derived class definition.)
 
C

Chris Gordon-Smith

James Kanze wrote:
[...]

True enough. In the case of my Action_Requests however, I
don't want to use the derived class' interface. I always want
to call polymorphically through the base interface.

In that case, you probably also want a factory which returns the
actual instances, so that the client code doesn't even know that
the derived classes exist. (And of course, in that case,
whether the virtual functions are public or are private in the
derived class really doesn't matter, since the client code
doesn't have access to the derived class definition.)

Yes. I have something like this. I make objects of the derived class
by reading input from a file. Depending on the kind of 'request' in
the file. I make an object of the appropriate derived class. Once this
has been done, nothing in the client code that manipulates the objects
knows about the derived classes.

(Hope this posting gets through OK. I can't get onto my news server at
the moment and so have had to go onto Google groups.)

Chris Gordon-Smith
www.simsoup.info
 
D

Daniel Pitts

Chris said:
James Kanze wrote: [...]

True enough. In the case of my Action_Requests however, I
don't want to use the derived class' interface. I always want
to call polymorphically through the base interface.
In that case, you probably also want a factory which returns the
actual instances, so that the client code doesn't even know that
the derived classes exist. (And of course, in that case,
whether the virtual functions are public or are private in the
derived class really doesn't matter, since the client code
doesn't have access to the derived class definition.)

Yes. I have something like this. I make objects of the derived class
by reading input from a file. Depending on the kind of 'request' in
the file. I make an object of the appropriate derived class. Once this
has been done, nothing in the client code that manipulates the objects
knows about the derived classes.

(Hope this posting gets through OK. I can't get onto my news server at
the moment and so have had to go onto Google groups.)

Chris Gordon-Smith
www.simsoup.info
If you want to "hide" the implementation classes from client code, put
them into a anonymous namespace. That way, they can't ever access the
symbols that represent them, and they can only ever have access to your
instance through base class pointers or references.
 
C

Chris Gordon-Smith

Daniel said:
Chris said:
On May 28, 6:13 pm, Chris Gordon-Smith <[email protected]>
wrote:

James Kanze wrote:
[...]

True enough. In the case of my Action_Requests however, I
don't want to use the derived class' interface. I always want
to call polymorphically through the base interface.
In that case, you probably also want a factory which returns the
actual instances, so that the client code doesn't even know that
the derived classes exist. (And of course, in that case,
whether the virtual functions are public or are private in the
derived class really doesn't matter, since the client code
doesn't have access to the derived class definition.)

Yes. I have something like this. I make objects of the derived class
by reading input from a file. Depending on the kind of 'request' in
the file. I make an object of the appropriate derived class. Once this
has been done, nothing in the client code that manipulates the objects
knows about the derived classes.

(Hope this posting gets through OK. I can't get onto my news server at
the moment and so have had to go onto Google groups.)

Chris Gordon-Smith
www.simsoup.info
If you want to "hide" the implementation classes from client code, put
them into a anonymous namespace. That way, they can't ever access the
symbols that represent them, and they can only ever have access to your
instance through base class pointers or references.

Interesting. I just tried that, but now unfortunately my program won't link
because my factory class can't see the derived class' constructor.

Chris Gordon-Smith
www.simsoup.info
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,755
Messages
2,569,536
Members
45,009
Latest member
GidgetGamb

Latest Threads

Top