 |
C++Talk.NET C++ language newsgroups
|
| View previous topic :: View next topic |
| Author |
Message |
Holger Sebert Guest
|
Posted: Thu Jun 22, 2006 3:59 pm Post subject: Deriving from concrete types |
|
|
Hi all,
I know that is in general a bad idea to derive from concrete types. However, I
wonder if it is o.k. if the derived class does not add any data members but only
extends the interface. For example:
class SpecialIntVector : public std::vector< int > {
public:
// ... int vector specific member functions go here ...
};
class SpecialFloatVector : public std::vector< float > {
public:
// ... float vector specific member functions go here ...
};
In this example, one automatically obtains STL-compatible vector types (except
for the constructors, of course) and has a syntactically clean extension of the
interface:
SpecialIntVector v;
v.resize( 1000 );
v.doSomethingSpecial();
Where are the problems with this approach?
Regards,
Holger
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ] |
|
| Back to top |
|
 |
Ulrich Eckhardt Guest
|
Posted: Fri Jun 23, 2006 2:59 pm Post subject: Re: Deriving from concrete types |
|
|
Holger Sebert wrote:
| Quote: | I know that is in general a bad idea to derive from concrete types.
|
....because when you delete them via a pointer to the baseclass, the
destructor is not invoked polymorphically, leading to undefined behaviour.
| Quote: | However, I wonder if it is o.k. if the derived class does not add any data
members but only extends the interface.
|
Still undefined behaviour.
| Quote: | SpecialIntVector v;
v.resize( 1000 );
v.doSomethingSpecial();
Where are the problems with this approach?
|
As said above. If that doesn't apply, there is still another question left:
why? std::vector has no virtual functions you could overwrite and no
protected members you would get access to, so what's the gain?
I'd rather do this:
vector<float> v(1000);
DoSomethingSpecial(v);
...or even this:
vector<float> v(1000);
DoSomethingSpecial(v.begin(), v.end());
...or perhaps the equivalent using ranges.
Uli
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ] |
|
| Back to top |
|
 |
Victor Bazarov Guest
|
Posted: Fri Jun 23, 2006 3:02 pm Post subject: Re: Deriving from concrete types |
|
|
Holger Sebert wrote:
| Quote: | I know that is in general a bad idea to derive from concrete types.
|
Oh, you *know* that, don't you? As if it's true...
| Quote: | However, I wonder if it is o.k. if the derived class does not add any
data members but only extends the interface.
|
Only if it truly *extends* it.
Deriving from a concrete type if perfectly fine. People do it all the
time and live to talk about it. There are no language problems in it.
The problems are of the OOD kind.
| Quote: | For example:
class SpecialIntVector : public std::vector< int > {
public:
// ... int vector specific member functions go here ...
|
Like what?
| Quote: | };
class SpecialFloatVector : public std::vector< float > {
public:
// ... float vector specific member functions go here ...
|
Again, like what?
| Quote: | };
In this example, one automatically obtains STL-compatible vector
types (except for the constructors, of course) and has a
syntactically clean extension of the interface:
SpecialIntVector v;
v.resize( 1000 );
v.doSomethingSpecial();
|
Special? Don't you mean, "SomethingEvenMoreGeneric"?
| Quote: | Where are the problems with this approach?
|
You mean, besides that you don't really describe what kind of
"extension" you're talking about?
This has been discussed so many times (try reading archives of the
'comp.object' newsgroup), I don't want to beat the dead horse. One
of the most often given examples is "extending" a string to model
a phone number. Or, "extending" a rectangle to model a square
(because we know that a square "is-a" rectangle, don't we?)
Again, there is no C++ language problem when it comes to inheriting
from a concrete class. A better place to ask would be comp.object,
since with public inheritance you may be violating the basic OOD
principle of substitutability. Of course, *private inheritance* is
a totally different bag of kittens, and is a very well-known and
widely used idiom, called "implement in terms of" (and ont "is-a").
V
--
Please remove capital 'A's when replying by e-mail
I do not respond to top-posted replies, please don't ask
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ] |
|
| Back to top |
|
 |
RenjithMohan Guest
|
Posted: Fri Jun 23, 2006 3:07 pm Post subject: Re: Deriving from concrete types |
|
|
Holger Sebert wrote:
| Quote: | Hi all,
I know that is in general a bad idea to derive from concrete types. However, I
wonder if it is o.k. if the derived class does not add any data members but only
extends the interface. For example:
class SpecialIntVector : public std::vector< int > {
public:
// ... int vector specific member functions go here ...
};
class SpecialFloatVector : public std::vector< float > {
public:
// ... float vector specific member functions go here ...
};
In this example, one automatically obtains STL-compatible vector types (except
for the constructors, of course) and has a syntactically clean extension of the
interface:
SpecialIntVector v;
v.resize( 1000 );
v.doSomethingSpecial();
Where are the problems with this approach?
Regards,
Holger
|
This has been discussed umpteen times in this and other newsgroups.
I will summarize the points
1)Generally speaking the STL containers are not intended to be used as
base classes.
It is evident from the fact that they dont have a virtual destructor.
And you know what happens when you delete a base pointer if the
contained object is a derived one. It is Undefined Behaviour.
If you provide such a class nothing prevents from your clients to do
so.
2)They dont have any protected members or virtual functions to warrant
the design of public inheritance.
If you need to provide enhanced functionality it is prefered to provide
non member functions to achieve this, much like the algorithms
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ] |
|
| Back to top |
|
 |
Pete Becker Guest
|
Posted: Sat Jun 24, 2006 2:31 pm Post subject: Re: Deriving from concrete types |
|
|
RenjithMohan wrote:
| Quote: |
1)Generally speaking the STL containers are not intended to be used as
base classes.
It is evident from the fact that they dont have a virtual destructor.
|
Non sequitur. What is evident from that fact is that you should not
delete an object of a derived type through a pointer to the base. There
are many uses of inheritance that do not require that sort of deletion.
| Quote: | And you know what happens when you delete a base pointer if the
contained object is a derived one. It is Undefined Behaviour.
|
That is, you don't know what happens.
| Quote: | If you provide such a class nothing prevents from your clients to do
so.
|
Nothing except their competence as programmers.
--
Pete Becker
Roundhouse Consulting, Ltd.
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ] |
|
| Back to top |
|
 |
Holger Sebert Guest
|
Posted: Sat Jun 24, 2006 2:34 pm Post subject: Re: Deriving from concrete types |
|
|
Ulrich Eckhardt wrote:
| Quote: | Holger Sebert wrote:
I know that is in general a bad idea to derive from concrete types.
...because when you delete them via a pointer to the baseclass, the
destructor is not invoked polymorphically, leading to undefined behaviour.
|
Ooops ... I did not know that it is /undefined behaviour/. I have thought that
in such a case the destructor of the base class is invoked, which I thought was
o.k. because there are no additional data members in the derived class (in this
case).
| Quote: | [...]
I'd rather do this:
vector<float> v(1000);
DoSomethingSpecial(v);
..or even this:
vector<float> v(1000);
DoSomethingSpecial(v.begin(), v.end());
..or perhaps the equivalent using ranges.
Uli
|
Well at least you would have something like a strong typedef in this case. This
is important if you have some operations which should only be applied to an,
e.g., SpecialFloatVector, and not an std::vector< float >. (I know of
boost::strong_typedef, but in my code I cannot use the boost libs).
Another point: Suppose you have a class X that must behave as a std::list<>, but
also has to have additional member functions (e.g. to provide an interface that
is consistent with other classes). How do you deal with that?
The only way I can think of is putting this std::list<> inside the class X as a
data member and write tons of delegate functions. But this becomes annoying
already if you have two or three of such cases ...
Regards,
Holger
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ] |
|
| Back to top |
|
 |
Alan McKenney Guest
|
Posted: Sat Jun 24, 2006 2:37 pm Post subject: Re: Deriving from concrete types |
|
|
RenjithMohan wrote:
<original post deleted>
| Quote: | This has been discussed umpteen times in this and other newsgroups.
I will summarize the points
1)Generally speaking the STL containers are not intended to be used as
base classes.
It is evident from the fact that they dont have a virtual destructor.
And you know what happens when you delete a base pointer if the
... object is a derived one. It is Undefined Behaviour.
If you provide such a class nothing prevents from your clients to do
so.
|
Except the same thing that prevents your clients from dereferencing
a null or deleted pointer: your clients' desire not to have their
programs crash.
To what extent should we use a convoluted solution instead
of an elegant solution just because a stupid user can use
it to make his program crash?
| Quote: | 2)They dont have any protected members or virtual functions to warrant
the design of public inheritance.
If you need to provide enhanced functionality it is prefered to provide
non member functions to achieve this, much like the algorithms
|
This particular bit of dogma, like much of the
catechism of the C++ One True Way that gets
trotted out at every opportunity, depends upon some
assumptions about how C++ code will be used.
This bit of dogma assumes:
1. All C++ classes are created by all-knowing library
writers, who know best how the class may and
may not be used, while C++ classes are used
by clueless idiots who don't read documentation
and will start WWIII if we're not careful.
Now I grant you, this applies in a lot of cases
(which are well-represented in this newsgroup), but
in my experience, there are a lot of cases where
the user of the classes may know more than the
implementer, and where the ability to use a class
in ways that the author never intended is precisely
what makes the class useful.
2. The only reason for derivation is to allow
polymorphic use (treating a derived
class as a base class.)
If you need an object which acts just like a
std::vector, but you need a little extra functionality,
then deriving from std::vector is the *obvious* thing
to do.
That way, you get all the std::vector behavior "for
free", and you only need to add the extra member
function or two to get the desired extra
functionality.
Note that I didn't say: I'm working with a bunch
of vectors, but I want one of my vectors to act a little
different from std::vector. Instead, I need a Whatsit,
and what I need Whatsits to do turns out to be pretty
much what a std::vector does, plus some stuff.
So we're not talking about polymorphic use, and
there's no reason to pass around with pointers
to std::vector , unless you're entering an obfuscated
C++ contest.
On another note: some posters have indicated that
one should use "private" inheritance.
Now, I've never used private inheritance, but it
seems to me that if you derive privately from std::vector,
then all the std::vector functions are inaccessible
to the user of the class, which sort of defeats the
purpose.
Free functions are doable, but then you have
issues of possible name clashes, and you can't
use the member function syntax.
-- Alan McKenney
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ] |
|
| Back to top |
|
 |
Guest
|
Posted: Sun Jun 25, 2006 6:55 pm Post subject: Re: Deriving from concrete types |
|
|
Holger Sebert 寋�:
| Quote: | Hi all,
I know that is in general a bad idea to derive from concrete types. However, I
wonder if it is o.k. if the derived class does not add any data members but only
extends the interface. For example:
..
|
If suitable, one can derive from any class. Polymorphical classes
are not without their drawbacks in derivation.
IJ. Wang
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ] |
|
| Back to top |
|
 |
Kirit Sælensminde Guest
|
Posted: Mon Jun 26, 2006 9:10 am Post subject: Re: Deriving from concrete types |
|
|
Alan McKenney wrote:
| Quote: | On another note: some posters have indicated that
one should use "private" inheritance.
Now, I've never used private inheritance, but it
seems to me that if you derive privately from std::vector,
then all the std::vector functions are inaccessible
to the user of the class, which sort of defeats the
purpose.
|
Read up on the 'using' syntax.
class MyVector : private std::vector< int > {
public:
using operator [];
using resize;
// etc.
};
Now you can control exactly the members that you wish to include and
you cannot use a MyVector as a substitute for any std::vector< int >
either.
Kirit
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ] |
|
| Back to top |
|
 |
Bernhard Jungk Guest
|
Posted: Mon Jun 26, 2006 9:10 am Post subject: Re: Deriving from concrete types |
|
|
| Quote: | 2. The only reason for derivation is to allow
polymorphic use (treating a derived
class as a base class.)
|
This isn't a dogma of the C++ community. It's a matter of good
OOD. Public inheritance is provided to allow polymorphic use.
The derived class has to be replaceable with the base class.
If the base class isn't designed to be derivable, it shouldn't be
done with public inheritance.
Public inheritance defines a "is a" relationship and
therefore the client is able to use an instance of the derived class
like an instance of the base class. All contracts of the base class
must hold. (e.g. it must be guaranteed, that the derived object may
be destructed correctly through a base pointer.)
Private (and protected) inheritance defines a "is implemented
in terms of" relationship. Which is similar to a composition, which
should be preferred over private inheritance, if possible.
| Quote: | Now, I've never used private inheritance, but it
seems to me that if you derive privately from std::vector,
then all the std::vector functions are inaccessible
to the user of the class, which sort of defeats the
purpose.
|
You can make the members publicly accessible again with a using
directive.
- Bernhard -
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ] |
|
| Back to top |
|
 |
kanze Guest
|
Posted: Tue Jun 27, 2006 4:23 pm Post subject: Re: Deriving from concrete types |
|
|
Bernhard Jungk wrote:
| Quote: | 2. The only reason for derivation is to allow
polymorphic use (treating a derived
class as a base class.)
This isn't a dogma of the C++ community. It's a matter of good
OOD. Public inheritance is provided to allow polymorphic use.
The derived class has to be replaceable with the base class.
|
That depends. I think your confusing derivation and
inheritance. Or whatever you want to call them; the confusion
often occurs, because there is no standard vocabulary for
distinguishing between:
-- an essential OO design pattern, in which a number of derived
types can be used indifferently in place of the base type,
and
-- a C++ implementation technique, which is often used to
implement the design pattern, but of course, can be used to
implement other patterns as well.
If you are using C++ inheritance to implement OO derivation (or
is it C++ derivation to implement OO inheritance---as I said,
there is no established vocabulary for making the distinction),
then the base class very definitly must be designed
intentionally to be a base class for OO derivation. Which
includes such things as having a virtual destructor. And which
std::vector is not. If you are using C++ inheritance for some
other reason, the other rules may apply; std::iterator is
certainly designed to be a base class in the C++ sense, even if
it has no virtual functions.
My experience has been that users tend to be able to cope with
this pretty well, as long as you've documented the role your
class was designed to fulfil. I've never heard of anyone trying
to delete an iterator through an std::iterator*, for example.
(For that matter, I don't think I've ever heard of anyone even
declaring an std::iterator*.)
| Quote: | If the base class isn't designed to be derivable, it shouldn't
be done with public inheritance.
|
You see. You've mixed the two. Inheritance is a C++
implementation technique; derivation is a design concept. If
the reason you are using inheritance is to implement derivation,
then you should ensure that your class is designed with
derivation in mind. If you are using it for some other reason,
you should ensure that your class meets the requirements for
whatever the reason.
| Quote: | Public inheritance defines a "is a" relationship
|
Public derivation defines a "is a" relationship. Public
inheritance is the obvious way to implement it. So much so that
I would say that public derivation implies public inheritance.
But it's not an if and only if relationship.
--
James Kanze GABI Software
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! ] |
|
| Back to top |
|
 |
Alan McKenney Guest
|
Posted: Tue Jun 27, 2006 4:33 pm Post subject: Re: Deriving from concrete types |
|
|
Bernhard Jungk wrote:
| Quote: | 2. The only reason for derivation is to allow
polymorphic use (treating a derived
class as a base class.)
... Public inheritance is provided to allow polymorphic use.
|
Perhaps in the OOD paradigm, this is the only reason for
public inheritance (I'm not an expert in OOD theory.)
However, one of C++'s strengths is that it supports
multiple paradigms. And one real non-OOD use of
derivation is code re-use, where there is no expectation
of polymorphic use.
The OP's example is, to my mind, a perfect example
of derivation for code re-use: a new class which is
similar to an existing class.
By using public inheritance, the new class definition
contains only those things which distinguish it from
the existing class, thus making it clear to anyone
who reads it what is going on.
(Yes, you can use private inheritance, but then
you have to put in a "using" declaration for every
base class function and operator. Quick, how
many of you can rattle off all the member functions
and operators in std::vector without looking at
the documentation?)
If Stroustrup had intended to create a language
which would force people to fit their code into
OOD paradigms, perhaps he would have made
it impossible to derive from a class with a non-virtual
destructor. Or made it impossible to override
non-virtual functions.
Fortunately, he did not.
And C++ is all the more useful for it.
(Just think of all the one-paradigm languages out there --
have *any* of them become more than niche languages?)
-- Alan McKenney
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ] |
|
| Back to top |
|
 |
Alan McKenney Guest
|
Posted: Tue Jun 27, 2006 4:33 pm Post subject: Re: Deriving from concrete types |
|
|
Kirit Sælensminde wrote:
| Quote: | Alan McKenney wrote:
On another note: some posters have indicated that
one should use "private" inheritance.
Now, I've never used private inheritance, but it
seems to me that if you derive privately from std::vector,
then all the std::vector functions are inaccessible
to the user of the class, which sort of defeats the
purpose.
Read up on the 'using' syntax.
class MyVector : private std::vector< int > {
public:
using operator [];
using resize;
// etc.
};
Now you can control exactly the members that you wish to include and
you cannot use a MyVector as a substitute for any std::vector< int
either.
|
True.
But if you want all the std::vector<> member functions, how is this
better than just using public inheritance?
A disadvantage of putting in "using" declarations for every
std::vector function is that it's an opportunity for errors and
omissions.
-- Alan McKenney
[line eater fodder]
[munch, munch]
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ] |
|
| Back to top |
|
 |
todma Guest
|
Posted: Tue Jun 27, 2006 4:36 pm Post subject: Re: Deriving from concrete types |
|
|
| Quote: | Read up on the 'using' syntax.
class MyVector : private std::vector< int > {
public:
using operator [];
using resize;
// etc.
};
Now you can control exactly the members that you wish to include and
you cannot use a MyVector as a substitute for any std::vector< int
either.
Kirit
Was 'using' created mainly to solve this problem? I guess this is a |
motivation to upgrade my compiler.
Was the small debate here over deriving from a class without virtual
destructors a classic debate that is now resolved via the 'using'
keyword?
This relates to my desire to derive classes from vector<> and pair<>.
Is this desire in fact misguided?
thanks,
Todd.
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ] |
|
| Back to top |
|
 |
Carl Barron Guest
|
Posted: Wed Jun 28, 2006 3:42 pm Post subject: Re: Deriving from concrete types |
|
|
In article <1151354600.564226.315500 (AT) r2g2000cwb (DOT) googlegroups.com>,
todma <toddmarshall2002 (AT) yahoo (DOT) com> wrote:
| Quote: | Read up on the 'using' syntax.
class MyVector : private std::vector< int > {
public:
using operator [];
using resize;
// etc.
};
Now you can control exactly the members that you wish to include and
you cannot use a MyVector as a substitute for any std::vector< int
either.
Kirit
Was 'using' created mainly to solve this problem? I guess this is a
motivation to upgrade my compiler.
Was the small debate here over deriving from a class without virtual
destructors a classic debate that is now resolved via the 'using'
keyword?
This relates to my desire to derive classes from vector<> and pair<>.
Is this desire in fact misguided?
thanks,
Todd.
The facts are these according to the standard [approved and 06 draft] |
but I quote 06 draft since I can copy and paste from it..
Section 11.2 paragraph 1 of N2009=06-0079 dated 2006-04-21 states:
<quote>
If a class is declared to be a base class (clause 10) for another class
using the public access specifier, the public
members of the base class are accessible as public members of the
derived class and protected members of the base
class are accessible as protected members of the derived class. If a
class is declared to be a base class for another
class using the protected access specifier, the public and protected
members of the base class are accessible as
protected members of the derived class. If a class is declared to be a
base class for another class using the private
access specifier, the public and protected members of the base class
are accessible as private members of the
derived class.
</quote>.
related footnote
<quote>
As specified previously in clause 11, private members of a base class
remain inaccessible even to derived classes unless friend declarations
within the base class definition are used to grant access explicitly.
</quote>
Therefore C++ inheritance is a superset of OOD inheritance/derivation.
Any other definition such as its an 'x a' relatiionship is a speial
case if the above descriptions hold. Deriving from a concrete class is
a legal reuse of code. See <stack> note the container used for the
stack is a PROTECTED member. so that special stacks can be written
without rewriting the entire std::stack class as something else.
If you are generally assuming C++ inheritance -> OOD inheritance you
are mistaken. OOD inheritance is included in C++'s public inheritance,
and is often the most often used use of public inheritance, but not the
only one. If you use C++ public inheritance, I do recommend you
document this is not an OOD inheritance, as unfortunately there is a
large number of programmers that assume, in error , that C++ public
inheritances is OOD inheritance.
To answer your question there is nothing wrong with deriving from
std::vector<T,A> as long as it is not used as an OOD inheritance. The
following is a stack, that allows random access read/write access to a
stack [not removal except the top].
struct my_stack:public std::stack<int,std::vector<int> >
{
int & operator [] (int n) { return c.operator [] (n);}
int & operator [] (int n) const {return c.operator[](n);}
};
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ] |
|
| Back to top |
|
 |
|
|
You cannot post new topics in this forum You cannot reply to topics in this forum You cannot edit your posts in this forum You cannot delete your posts in this forum You cannot vote in polls in this forum
|
|