Inheriting a vector

T

toton

Hi,
I want to have a vector like class with some additional functionality
(cosmetic one). So can I inherit a vector class to add the addition
function like,

CorresVector : public vector<Corres>{
public:
void addCorres(Corres& c); //it do little more than push_back
function.
}
Or I need to do a composition to do it (i.e storing the vector inside
Corresvector & delegating the necessary functionality). I want to know
that whether in this case (inheriting) is allowed for containers, i.e
will the container will get freed when CorresVector gets destoryed (i.e
vector has a virtual destructor which gets called?)

abir
 
N

Noah Roberts

toton said:
Hi,
I want to have a vector like class with some additional functionality
(cosmetic one). So can I inherit a vector class to add the addition
function like,

CorresVector : public vector<Corres>{
public:
void addCorres(Corres& c); //it do little more than push_back
function.
}
Or I need to do a composition to do it (i.e storing the vector inside
Corresvector & delegating the necessary functionality). I want to know
that whether in this case (inheriting) is allowed for containers, i.e
will the container will get freed when CorresVector gets destoryed (i.e
vector has a virtual destructor which gets called?)

No, vector does not have a virtual destructor. It doesn't have any
virtual functions. You can inherit from a vector but you can't do so
polymorphically.
 
F

Frank

toton said:
Hi,
I want to have a vector like class with some additional functionality
(cosmetic one). So can I inherit a vector class to add the addition
function like,

CorresVector : public vector<Corres>{
public:
void addCorres(Corres& c); //it do little more than push_back
function.
}
Or I need to do a composition to do it (i.e storing the vector inside
Corresvector & delegating the necessary functionality). I want to know
that whether in this case (inheriting) is allowed for containers, i.e
will the container will get freed when CorresVector gets destoryed (i.e
vector has a virtual destructor which gets called?)

abir

Hi abir,

std::vector does not have a virtual destructor.
But it would only need one, if you delete a CorresVector through a pointer
to a base class.

As for the question whether it is the "right" approach, use google and you
will find a lot of different opinions (see e.g.
http://www.thescripts.com/forum/thread63869.html).

Cheers,
Frank
 
T

toton

Frank said:
Hi abir,

std::vector does not have a virtual destructor.
But it would only need one, if you delete a CorresVector through a pointer
to a base class.

As for the question whether it is the "right" approach, use google and you
will find a lot of different opinions (see e.g.
http://www.thescripts.com/forum/thread63869.html).
I have a Session class which stores the CorresVector, not a pointer or
reference. and Session class destructor will thus automatically call
CorresVector. Hence there is no ploymorphic behavior. I hope there will
not be any memory leak therefore.
Otherwise it is pain to delegate a lot of method including container
traits & iterators.
Religion is definitely a question, may think later of delegating (or
protected inheritence) if my class sufficiently differs from vector or
any other misuse question comes (I know Java Stack is inherited from
Vector ! ).
 
T

toton

Frank said:
Hi abir,

std::vector does not have a virtual destructor.
But it would only need one, if you delete a CorresVector through a pointer
to a base class.

As for the question whether it is the "right" approach, use google and you
will find a lot of different opinions (see e.g.
http://www.thescripts.com/forum/thread63869.html).
I have a Session class which stores the CorresVector, not a pointer or
reference. and Session class destructor will thus automatically call
CorresVector. Hence there is no ploymorphic behavior. I hope there will
not be any memory leak therefore.
Otherwise it is pain to delegate a lot of method including container
traits & iterators.
Religion is definitely a question, may think later of delegating (or
protected inheritence) if my class sufficiently differs from vector or
any other misuse question comes (I know Java Stack is inherited from
Vector ! ).
Thanks for quick answer.
 
S

Salt_Peter

toton said:
Hi,
I want to have a vector like class with some additional functionality
(cosmetic one). So can I inherit a vector class to add the addition
function like,

CorresVector : public vector<Corres>{
public:
void addCorres(Corres& c); //it do little more than push_back
function.
}
Or I need to do a composition to do it (i.e storing the vector inside
Corresvector & delegating the necessary functionality). I want to know
that whether in this case (inheriting) is allowed for containers, i.e
will the container will get freed when CorresVector gets destoryed (i.e
vector has a virtual destructor which gets called?)

abir

You should not derive from STL container classes. Their destructors are
not virtual.
Although, in my book, composition can be a form of private inheritence.
Why not template the class? In your example, if element class Corres,
whatever that is, overloads the global op<<, you can add features as
shown below. Note that both primitive int and class std::string already
have an overloaded operator<<.

The point here is that if you are going to compose with a std::vector,
do it to add features, otherwise you would not need to wrap the
container.
How you do that is not very complicated:

a) learn how to declare and use templates
b) pass by reference
c) dependant types need the typename keyword
d) overload operators

#include <iostream>
#include <ostream>
#include <string>
#include <vector>

template< typename T >
class Vector
{
std::vector< T > vt;
public:
Vector() : vt() { } // an empty vector of TsSince primitive types
like int and other classes like std::string already have an overload
for global op<<, i can iterate through the elements simply by writing:

std::cout << name_of_container;
~Vector() { }
/* member functions */
size_t size() const { return vt.size(); }
void push_back( const T& r_t ) { vt.push_back( r_t ); }
/* friend op */
friend
std::eek:stream&
operator<<( std::eek:stream& os, Vector< T >& r_v )
{ // std::vector<T>::iterator is a dependant type
typedef typename std::vector< T >::iterator VIter;
VIter iter = r_v.vt.begin();
for ( iter; iter != r_v.vt.end(); ++iter )
{
os << *iter << std::endl;
}
return os;
}
};

int main()
{
Vector< int > integers;
for ( int n = 0; n < 5; ++n )
{
integers.push_back( n );
}
std::cout << integers; // op<< overload

Vector< std::string > strings;
strings.push_back( "first string" );
strings.push_back( "second string" );
strings.push_back( "third string" );
strings.push_back( "fourth string" );
std::cout << strings; // op<< overload

return 0;
}

/*
0
1
2
3
4
first string
second string
third string
fourth string
*/
 
T

toton

Salt_Peter said:
You should not derive from STL container classes. Their destructors are
not virtual.
Although, in my book, composition can be a form of private inheritence.
Why not template the class? In your example, if element class Corres,
whatever that is, overloads the global op<<, you can add features as
shown below. Note that both primitive int and class std::string already
have an overloaded operator<<.

The point here is that if you are going to compose with a std::vector,
do it to add features, otherwise you would not need to wrap the
container.
How you do that is not very complicated:

a) learn how to declare and use templates
b) pass by reference
c) dependant types need the typename keyword
d) overload operators

#include <iostream>
#include <ostream>
#include <string>
#include <vector>

template< typename T >
class Vector
{
std::vector< T > vt;
public:
Vector() : vt() { } // an empty vector of TsSince primitive types
like int and other classes like std::string already have an overload
for global op<<, i can iterate through the elements simply by writing:

std::cout << name_of_container;
~Vector() { }
/* member functions */
size_t size() const { return vt.size(); }
void push_back( const T& r_t ) { vt.push_back( r_t ); }
/* friend op */
friend
std::eek:stream&
operator<<( std::eek:stream& os, Vector< T >& r_v )
{ // std::vector<T>::iterator is a dependant type
typedef typename std::vector< T >::iterator VIter;
VIter iter = r_v.vt.begin();
for ( iter; iter != r_v.vt.end(); ++iter )
{
os << *iter << std::endl;
}
return os;
}
};

int main()
{
Vector< int > integers;
for ( int n = 0; n < 5; ++n )
{
integers.push_back( n );
}
std::cout << integers; // op<< overload

Vector< std::string > strings;
strings.push_back( "first string" );
strings.push_back( "second string" );
strings.push_back( "third string" );
strings.push_back( "fourth string" );
std::cout << strings; // op<< overload

return 0;
}

/*
0
1
2
3
4
first string
second string
third string
fourth string
*/
This is the other option which I thought (and mentioned in my first
post). Using delegate is always better, I think. It both protects
security, and makes a cleaner interface (I had mentioned like Java
Vector & Stack). And templating Vector is not usefull for my case, as I
am going to use only and only CorresVector where some additional
methods are there, to perform some additional job, and may want to
build a library from that directly for my core engine part of the
application. Not that it can not be done otherway, (like performing
the tasks after push_back operation, say some notification event
handling) but assigning the tasks in the operation itself secures code.

However unlike the code you presented, I need many features of vector
rather than just push_back. Most importantly, I need the iterator
functionality, and want to apply many stl algorithms to CorresVector
just like vector. That says I need to delegate many more functions
rather than size & push_back( say aoo of the iterator traits, const &
non const vercion of begin end etc, reserve, indexing operators, at and
others). It is not difficult, it is tedious!
And in code CorresVector is going to be used only one place, i.e inside
Session class, like,
class Session{
private:
CorresVector _corres;
};
and some reference get methods (const & non const). There is no other
place where it will be used (there is no other place there it can be
used also :) ). Thus I think it will not cause any memory leak in this
particular case(i.e not freeing the elements on destruction). Session
class has a virtual destructor, and hence it will always get destroyed
even when inheriting & storing in SessionManager (a singleton) like
FileSession, OnlineSession etc.
Can you say a yes/no about risk to this specific case?
For general case, I like your answer, and sooner or later will
implement it.
btw Corres means Correspondence (a special kind of distance structure)

Thanks for the reply & the worning.
 
G

Gavin Deane

Salt_Peter said:
You should not derive from STL container classes. Their destructors are
not virtual.

That should read "you should not polymorphically delete objects of
types derived from STL container classes. STL container classes do not
have virtual destructors."
Although, in my book, composition can be a form of private inheritence.
Why not template the class? In your example, if element class Corres,
whatever that is, overloads the global op<<, you can add features as
shown below. Note that both primitive int and class std::string already
have an overloaded operator<<.

The point here is that if you are going to compose with a std::vector,
do it to add features, otherwise you would not need to wrap the
container.
How you do that is not very complicated:

a) learn how to declare and use templates
b) pass by reference
c) dependant types need the typename keyword
d) overload operators

#include <iostream>
#include <ostream>
#include <string>
#include <vector>

template< typename T >
class Vector
{
std::vector< T > vt;
public:
Vector() : vt() { } // an empty vector of TsSince primitive types
like int and other classes like std::string already have an overload
for global op<<, i can iterate through the elements simply by writing:

std::cout << name_of_container;
~Vector() { }
/* member functions */
size_t size() const { return vt.size(); }
void push_back( const T& r_t ) { vt.push_back( r_t ); }
/* friend op */
friend
std::eek:stream&
operator<<( std::eek:stream& os, Vector< T >& r_v )
{ // std::vector<T>::iterator is a dependant type
typedef typename std::vector< T >::iterator VIter;
VIter iter = r_v.vt.begin();
for ( iter; iter != r_v.vt.end(); ++iter )
{
os << *iter << std::endl;
}
return os;
}
};

How is that class superior to this? If used with your program below it
produces the same output.

template <typename T>
class Vector : public std::vector<T>
{
friend std::eek:stream& operator<<(std::eek:stream& os, Vector< T >& r_v)
{
typedef typename std::vector< T >::iterator VIter;
VIter iter = r_v.begin();
for ( iter; iter != r_v.end(); ++iter )
{
os << *iter << std::endl;
}
return os;
}
};
int main()
{
Vector< int > integers;
for ( int n = 0; n < 5; ++n )
{
integers.push_back( n );
}
std::cout << integers; // op<< overload

Vector< std::string > strings;
strings.push_back( "first string" );
strings.push_back( "second string" );
strings.push_back( "third string" );
strings.push_back( "fourth string" );
std::cout << strings; // op<< overload

But your class can't do this unless you go back and change it.

strings.pop_back();
std::cout << strings;
return 0;
}

/*
0
1
2
3
4
first string
second string
third string
fourth string
first string
second string
third string

Gavin Deane
 
P

Pete Becker

Noah said:
No, vector does not have a virtual destructor. It doesn't have any
virtual functions. You can inherit from a vector but you can't do so
polymorphically.

But that's really two different questions. Yes, when CorresVector gets
destroyed, its base will, too. No, if you have a pointer to the base and
you delete that, you have no guarantees of what will happen, because the
base type does not have a virtual destructor.

--

-- Pete

Author of "The Standard C++ Library Extensions: a Tutorial and
Reference." For more information about this book, see
www.petebecker.com/tr1book.
 
S

Salt_Peter

Gavin said:
That should read "you should not polymorphically delete objects of
> types derived from STL container classes. STL container classes do not
have virtual destructors."

yes, of course. But isn't that the goal here?
Otherwise, why bother inheriting from a std::vector?
How is that class superior to this? If used with your program below it
produces the same output.

My class is not superior in any way unless there is a need to protect
the internals or if polymorphism is involved.
template <typename T>
class Vector : public std::vector<T>
{

If you inherit publicly, friend is no longer required, the std::vector
is directly accessible.
friend std::eek:stream& operator<<(std::eek:stream& os, Vector< T >& r_v)
{
typedef typename std::vector< T >::iterator VIter;
VIter iter = r_v.begin();
for ( iter; iter != r_v.end(); ++iter )
{
os << *iter << std::endl;
}
return os;
}
};

or

#include <iostream>
#include <ostream>
#include <string>
#include <vector>
#include <iterator>

template< typename T >
class Vector : public std::vector< T >
{
};

template< typename T >
std::eek:stream&
operator<<( std::eek:stream& os, Vector< T >& r_v )
{
std::copy( r_v.begin(),
r_v.end(),
std::eek:stream_iterator< T > ( std::cout , "\n") );
}

Which again brings us right back to the crux of the issue. In such a
case, why bother inheriting from std::vector? What is the reason?
But your class can't do this unless you go back and change it.

strings.pop_back();
std::cout << strings;

Thats obvious. The rest of the interface was not implemented.
 
G

Gavin Deane

Salt_Peter said:
yes, of course. But isn't that the goal here?
Otherwise, why bother inheriting from a std::vector?

I doubt polymorphism is the OP's goal, since std::vector doesn't have
any virtual member functions at all.
#include <iostream>
#include <ostream>
#include <string>
#include <vector>
#include <iterator>

template< typename T >
class Vector : public std::vector< T >
{
};

template< typename T >
std::eek:stream&
operator<<( std::eek:stream& os, Vector< T >& r_v )
{
std::copy( r_v.begin(),
r_v.end(),
std::eek:stream_iterator< T > ( std::cout , "\n") );
}

Which again brings us right back to the crux of the issue. In such a
case, why bother inheriting from std::vector? What is the reason?

That's a design decision for the OP. Depending on the design goal,
there may be options superior to inheritance. Composition may or may
not be one of them.

The point I was making was that lack of a virtual destructor is not
sufficient reason for rejecting inheritance, and that using composition
instead is not necessarily better because you, the programmer, are
required to manually forward all those parts of the std::vector
interface that you need to be accessible to users of the containing
class, whereas inheritance gives you that forwarding for free.
Thats obvious. The rest of the interface was not implemented.

The fact that it has to be implemented manually is the problem.

Gavin Deane
 
T

tragomaskhalos

toton said:
Hi,
I want to have a vector like class with some additional functionality
(cosmetic one). So can I inherit a vector class to add the addition
function like,

CorresVector : public vector<Corres>{
public:
void addCorres(Corres& c); //it do little more than push_back
function.
}

You are basically wanting to "inherit for convenience" - you seem like
a sensible fellow who understands that (a) there are issues with this
approach and (b) knows what those issues are (or at least you do know
from others' replies), so I say go for it.
 
J

Jerry Coffin

Hi,
I want to have a vector like class with some additional functionality
(cosmetic one). So can I inherit a vector class to add the addition
function like,

CorresVector : public vector<Corres>{
public:
void addCorres(Corres& c); //it do little more than push_back
function.
}
Or I need to do a composition to do it (i.e storing the vector inside
Corresvector & delegating the necessary functionality). I want to know
that whether in this case (inheriting) is allowed for containers, i.e
will the container will get freed when CorresVector gets destoryed (i.e
vector has a virtual destructor which gets called?)

std::vector doesn't have a virtual dtor (or any virtual functions for
that matter). Since the dtor isn't virtual this would lead to undefined
behavior, but it's easy to do by accident because public inheritance
allows implicit conversion to the base class.

While composition is clearly an option, you might also want to consider
private inheritance:

class CorresVector : private std::vector<Corres> {
public:
using vector::begin;
using vector::end;
using vector::erase;
void add(Corres const &c) { push_back(c); }
// ...
};

Public inheritance is easy, but somewhat dangerous because you can
accidentally (implicitly) convert a pointer to your derived class into a
pointer to the base -- and destroying that leads to undefined behavior.

Composition gives safety, but writing forwarding functions adds work.
Private inheritance is more or less a halfway point, providing the
safety of composition with a little less work -- using declarations are
clearly simpler than forwarding functions, though obviously more work
than a public base class.
 
P

Pete Becker

Jerry said:
std::vector doesn't have a virtual dtor (or any virtual functions for
that matter). Since the dtor isn't virtual this would lead to undefined
behavior

No, there's nothing undefined in destroying an object whose type is
derived from a type that does not have a virtual destructor. You ONLY
get undefined behavior if you delete such an object through a pointer to
its base type.

, but it's easy to do by accident because public inheritance
allows implicit conversion to the base class.

This has nothing to do with destruction. Converting to the base type is
slicing, and it's a potential problem regardless of whether the base
type has virtual functions.
Public inheritance is easy, but somewhat dangerous because you can
accidentally (implicitly) convert a pointer to your derived class into a
pointer to the base -- and destroying that leads to undefined behavior.

Composition gives safety, but writing forwarding functions adds work.
Private inheritance is more or less a halfway point, providing the
safety of composition with a little less work -- using declarations are
clearly simpler than forwarding functions, though obviously more work
than a public base class.

Okay.

--

-- Pete

Author of "The Standard C++ Library Extensions: a Tutorial and
Reference." For more information about this book, see
www.petebecker.com/tr1book.
 
J

Jerry Coffin

[ ... ]
No, there's nothing undefined in destroying an object whose type is
derived from a type that does not have a virtual destructor. You ONLY
get undefined behavior if you delete such an object through a pointer to
its base type.

Well, even I can't figure out what I wrote when you pull it apart into
half-sentences, and reply to bits and pieces that were never intended to
represent a complete thought. To clarify what I was trying to say:

1) if you have code like this:

class base {}; // note lack of virtual dtor
class derived : public base {};

base *b = new derived;
// ...
delete b;

You'd get undefined behavior. and:

2) There's absolutely NOTHING you can do in 'derived' to prevent it from
being used in that fashion (or many similar ones that cause similar
problems).

What it comes down to is fairly simple: by using public derivation,
you've _promised_ that a derived can be substituted for a base under any
and all possible circumstances. The problem arises for the simple reason
that this is a lie -- under at least one circumstance (destruction) the
substitution leads to undefined behavior.

In short, even though you _can_ get away with this as long as you're
sufficiently careful about how you use it, it's a lousy idea. Public
derivation has a specific meaning. Unless you really mean it, you
shouldn't say it by using public derivation. Public derivation from a
base class without a virtual dtor asserts a falsehood.
 
K

Kai-Uwe Bux

Jerry said:
[ ... ]
No, there's nothing undefined in destroying an object whose type is
derived from a type that does not have a virtual destructor. You ONLY
get undefined behavior if you delete such an object through a pointer to
its base type.

Well, even I can't figure out what I wrote when you pull it apart into
half-sentences, and reply to bits and pieces that were never intended to
represent a complete thought. To clarify what I was trying to say:

1) if you have code like this:

class base {}; // note lack of virtual dtor
class derived : public base {};

base *b = new derived;
// ...
delete b;

You'd get undefined behavior. and:

2) There's absolutely NOTHING you can do in 'derived' to prevent it from
being used in that fashion (or many similar ones that cause similar
problems).

What it comes down to is fairly simple: by using public derivation,
you've _promised_ that a derived can be substituted for a base under any
and all possible circumstances.

That seems false: since the language allows public derivation of classes
without virtual destructor, public inheritance obviously does not _promise_
that a derived class can be substituted for a base under _any_
circumstances. If it did, the standard would require the destructor of a
public base to be virtual. In fact, public inheritance per se does not
promise anything but the behavior guaranteed by the standard. Any claims
and connotations beyond the technical meaning of public inheritance are
part of (local) coding standards and style guides. Those might be more or
less well-founded and lay out best practices, but they do not define a
contract for public inheritance. Most importantly, such guidelines are in
my experience always closely tied to a certain domain or programing
paradigm, e.g., OO. In a given context, they can be perfectly valid.
Presented as universal truths about C++ programming, they turn into
falsehoods rather quickly.
The problem arises for the simple reason
that this is a lie -- under at least one circumstance (destruction) the
substitution leads to undefined behavior.

In short, even though you _can_ get away with this as long as you're
sufficiently careful about how you use it, it's a lousy idea. Public
derivation has a specific meaning.

(a) The only universal meaning of public inheritance is the one provided by
the standard, which does not require a virtual destructor.

(b) In certain contexts (e.g., OO) public inheritance can acquire another
meaning, e.g., the principle of substitutability that you outlines above.
Those meanings, however, are context specific.
Unless you really mean it, you
shouldn't say it by using public derivation. Public derivation from a
base class without a virtual dtor asserts a falsehood.

Nope. See for instance std::unary_function or std::iterator. Inheriting
publicly from those classes is perfectly fine and does not assert any
falsehoods. It just happens to be outside the scope of OO design and is
more closely related to generic programming. In that context, public
inheritance from base classes without virtual destructor is quite common
and nobody knowing the corresponding idioms will read public inheritance as
indicating substitutability in all contexts.


Best

Kai-Uwe Bux
 
T

toton

Kai-Uwe Bux said:
Jerry said:
[ ... ]
No, there's nothing undefined in destroying an object whose type is
derived from a type that does not have a virtual destructor. You ONLY
get undefined behavior if you delete such an object through a pointer to
its base type.

Well, even I can't figure out what I wrote when you pull it apart into
half-sentences, and reply to bits and pieces that were never intended to
represent a complete thought. To clarify what I was trying to say:

1) if you have code like this:

class base {}; // note lack of virtual dtor
class derived : public base {};

base *b = new derived;
// ...
delete b;

You'd get undefined behavior. and:

2) There's absolutely NOTHING you can do in 'derived' to prevent it from
being used in that fashion (or many similar ones that cause similar
problems).

What it comes down to is fairly simple: by using public derivation,
you've _promised_ that a derived can be substituted for a base under any
and all possible circumstances.

That seems false: since the language allows public derivation of classes
without virtual destructor, public inheritance obviously does not _promise_
that a derived class can be substituted for a base under _any_
circumstances. If it did, the standard would require the destructor of a
public base to be virtual. In fact, public inheritance per se does not
promise anything but the behavior guaranteed by the standard. Any claims
and connotations beyond the technical meaning of public inheritance are
part of (local) coding standards and style guides. Those might be more or
less well-founded and lay out best practices, but they do not define a
contract for public inheritance. Most importantly, such guidelines are in
my experience always closely tied to a certain domain or programing
paradigm, e.g., OO. In a given context, they can be perfectly valid.
Presented as universal truths about C++ programming, they turn into
falsehoods rather quickly.
The problem arises for the simple reason
that this is a lie -- under at least one circumstance (destruction) the
substitution leads to undefined behavior.

In short, even though you _can_ get away with this as long as you're
sufficiently careful about how you use it, it's a lousy idea. Public
derivation has a specific meaning.

(a) The only universal meaning of public inheritance is the one provided by
the standard, which does not require a virtual destructor.

(b) In certain contexts (e.g., OO) public inheritance can acquire another
meaning, e.g., the principle of substitutability that you outlines above.
Those meanings, however, are context specific.
Unless you really mean it, you
shouldn't say it by using public derivation. Public derivation from a
base class without a virtual dtor asserts a falsehood.

Nope. See for instance std::unary_function or std::iterator. Inheriting
publicly from those classes is perfectly fine and does not assert any
falsehoods. It just happens to be outside the scope of OO design and is
more closely related to generic programming. In that context, public
inheritance from base classes without virtual destructor is quite common
and nobody knowing the corresponding idioms will read public inheritance as
indicating substitutability in all contexts.


Best

Kai-Uwe Bux
The best thing I have learned from all these topics is that in C++
nothing can be prevented from being misused, whatever security you may
impose. And absolute security is absolutely not possible. C++ can only
tell you that "it is designed for this purpose, dont use it otherways."
The whole language and STL is designed that way (one can go out of
index, iterator can go out of range, iterator dont know their state or
the container, algo cant remove value from container, auto_ptr can be
passed by value, typesafe enum's are not enough type safe, destructors
are not virtual by default, yet it doesn't specify a final keyword to
prevent inheritance, const function can return non const reference,
delete can't set the class instance as null, null is simply an int,
bool gets automatically converted to int, ctor call and function decl
has same signature, ctor can not be delegated, yet it is allowed as
syntax, pointer and array are same yet they have same meaning only on
POD, << thinks it as shift operator, and many other). I really have to
think of an example where a class can not be misused! .
So the best thing I can do in my program ( I am the OP ! ) make a
comment ,"It is designed to use in that way, don't use it other way!" .
It will be foolish to prevent all such misuses, as there is no way I
can prevent all or some of them.
(BTW I had a post in the article for one such misuse(or mistake) and
ways to prevent is,
http://groups.google.com/group/comp...c77c5?lnk=gst&q=toton&rnum=2#aecb217bb11c77c5
but Victor Bazarov hadn't agreed with me, saying "There is no free
cheese, except in a mouse trap. ". Yesterady I discovered around a
dozon such trap where "programmers" went just by mistake (not for free
chese) and got trapped. The result is simple program crash (Silently!
giving some nonhuman readable message in windows box, and leaving no
clue for the origin of the error! )
So, "enjoy programming. If something unfortunate happens (even if it
destroyes the whole world!) don't blame me. It was NOT designed for
that purpose! ".
Cheers
 
K

Kai-Uwe Bux

toton wrote:
[snip}
The best thing I have learned from all these topics is that in C++
nothing can be prevented from being misused, whatever security you may
impose. And absolute security is absolutely not possible. C++ can only
tell you that "it is designed for this purpose, dont use it otherways."
The whole language and STL is designed that way (one can go out of
index, iterator can go out of range, iterator dont know their state or
the container, algo cant remove value from container, auto_ptr can be
passed by value, typesafe enum's are not enough type safe, destructors
are not virtual by default, yet it doesn't specify a final keyword to
prevent inheritance, const function can return non const reference,
delete can't set the class instance as null, null is simply an int,
bool gets automatically converted to int, ctor call and function decl
has same signature, ctor can not be delegated, yet it is allowed as
syntax, pointer and array are same yet they have same meaning only on
POD, << thinks it as shift operator, and many other). I really have to
think of an example where a class can not be misused! .
So the best thing I can do in my program ( I am the OP ! ) make a
comment ,"It is designed to use in that way, don't use it other way!" .
It will be foolish to prevent all such misuses, as there is no way I
can prevent all or some of them.
[snip]

Well put. There seem to be two schools of thought: one school emphasizes the
methods of tying the client down so that it cannot go astray; the other
school emphasizes the goal of designing a useful class and accepts that
undefined behavior may result from violating the preconditions of the
specified contract. The STL is an example for the later and, in my opinion,
establishes a precedence: it is at least not totally out of line to use
that approach to class design in C++.

That said, there is almost a continuum of design choices and some are more
hazardous than others. I would not go out of my way to safeguard against
all possible misuses, but I would also not propose a design that requires
each user of the class to read all the fine print to use it for simple
tasks without running into undefined behavior.

In the end, I think, each class should come with a set of recommended idioms
for safe use; and users should know that they have to be careful once they
depart from the recommended idioms and have to read the actual contracts.


Best

Kai-Uwe Bux
 
J

Jerry Coffin

[ ... ]
That seems false: since the language allows public derivation of classes
without virtual destructor, public inheritance obviously does not _promise_
that a derived class can be substituted for a base under _any_
circumstances.

You're takin the fact that something is standardized as meaning there
must be some circumstance under which it should be done, or is
meaningful, etc?

While I'm certainly not going to get into a long discussion over it,
this strikes me as fallacious reasoning. I guess if (for example) you
insist there's a good time to use gets, you can go ahead and do that. I
hope you'll forgive me if I pass. While I'll openly admit this isn't
_as_ dangerous as gets, it's still a bad idea -- there's simply no good
reason to do it. If you're deriving for the sake of convenience, and
don't want to allow (for example) pointers/references to your derived
class to be converted implicitly to pointers/references to the base
class, you have a choice of private or protected inheritance.
 
J

Jerry Coffin

[ ... ]
Well put. There seem to be two schools of thought: one school emphasizes the
methods of tying the client down so that it cannot go astray; the other
school emphasizes the goal of designing a useful class and accepts that
undefined behavior may result from violating the preconditions of the
specified contract.

Pardon my being blunt, but this is barely short of complete nonsense.
Attempting to write your class in a way that it's reasonably safe isn't
tying the client down.

A design does not have to encourage its clients to shoot themselves in
the feet to be useful.
 

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

Forum statistics

Threads
473,767
Messages
2,569,572
Members
45,045
Latest member
DRCM

Latest Threads

Top