By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
457,760 Members | 1,202 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 457,760 IT Pros & Developers. It's quick & easy.

Templated containers of inherited objects

P: n/a
Hi everyone,

I'd like your help...

Can we have a std::list<BASEwhere BASE be the base class of a class
hierarchy? I want to add to this list objects that are inherited from
BASE class but not necessarily the same...

class base {
int x;
};

class child1 : public base {
int d;
};

class child2 : public base {
int e;
};

int main() {
std::list<basemylist;
child1 _c1;
child2 _c2;
mylist.push_back(_c1);
mylist.push_back(_c2);
return 0;
}

It seems that I lose the information of _c1 and _c2 like they are
converted to base.

Please, do you have any idea how can I achieve that? Do I have to
implement my own container?

Many thanks in advance,
-- George

Feb 16 '07 #1
Share this Question
Share on Google+
21 Replies


P: n/a
George Exarchakos wrote:
>

Can we have a std::list<BASEwhere BASE be the base class of a class
hierarchy? I want to add to this list objects that are inherited from
BASE class but not necessarily the same...

[redacted]

Please, do you have any idea how can I achieve that? Do I have to
implement my own container?
You've run into the slicing problem. You need to create a container of
(smart) pointers to your base class.

That is, std::list<base*>, or std::list<some_smart_ptr<base

See the FAQ, http://www.parashift.com/c++-faq-lit....html#faq-34.4


Feb 16 '07 #2

P: n/a
On Feb 16, 5:51 pm, red floyd <no.s...@here.dudewrote:
George Exarchakos wrote:
Can we have a std::list<BASEwhere BASE be the base class of a class
hierarchy? I want to add to this list objects that are inherited from
BASE class but not necessarily the same...
[redacted]
>
Please, do you have any idea how can I achieve that? Do I have to
implement my own container?

You've run into the slicing problem. You need to create a container of
(smart) pointers to your base class.

That is, std::list<base*>, or std::list<some_smart_ptr<base

See the FAQ,http://www.parashift.com/c++-faq-lit....html#faq-34.4
Many thanks Red Floyd! This tip is exactly what I was looking for...
-- George

Feb 16 '07 #3

P: n/a
On 16 Feb 2007 09:17:51 -0800, "George Exarchakos" wrote:
>Can we have a std::list<BASEwhere BASE be the base class of a class
hierarchy? I want to add to this list objects that are inherited from
BASE class but not necessarily the same...
STL does not support object-oriented programming. STL containers,
iterators and algorithms are designed only for values, not for
(pointers to) objects. Workarounds exist but with 'Standard' STL there
always remains an 'impedance mismatch' when objects are used.

Best regards,
Roland Pibinger
Feb 16 '07 #4

P: n/a
On Feb 16, 1:05 pm, rpbg...@yahoo.com (Roland Pibinger) wrote:
On 16 Feb 2007 09:17:51 -0800, "George Exarchakos" wrote:
Can we have a std::list<BASEwhere BASE be the base class of a class
hierarchy? I want to add to this list objects that are inherited from
BASE class but not necessarily the same...

STL does not support object-oriented programming.
I think that this comment is misleading. If I understand the point of
the statement, its that using objects that use polymorphism in a
container isn't supported. Because this isn't the case at all.
Although, objects used with the STL must provide certain concepts,
such as default constructibility, copy constructibility et al.

When dealing with class hierarchies, we must pay special attention to
copy constructibility and other concepts because these can lead to
problems such as slicing as noticed by the OP.

Using pointers is a perfectly valid method of fixing this issue.

On the other hand, if Roland meant that "You can't subclass objects
such as std::vector." then he is in fact correct. IIRC, most stl
objects don't provide a virtual destructor. And further, the STL (as
its name suggests) is a library of templates. Using templates with
inheritance is at best tricky.

I'm not sure what the actual standard has to say on this, but g++
4.0.2 won't compile this:

class A
{
public:
A() {}
~A() {}

template< typename TYPE >
virtual void
echo( TYPE val ) = 0 ;
} ;

The error is:
error: invalid use of 'virtual' in template declaration of 'virtual
void A::echo(TYPE)'

This all makes sense if we think in terms of the (non-standard
dictated) vtable implementation of polymorphism. When we create the
vtable for A, we have no idea how many entries it will have.
Theoretically, it would need to have an entry for every template
instantiation of A::echo(TYPE).

Whats more, this class definition could possibly change after it has
been compiled. Ie, compiled in a library, then some client code calls
A::echo(TYPE) with a type thats not used in the library. Thus the
vtable would change and break all sorts of things.

STL containers,
iterators and algorithms are designed only for values, not for
(pointers to) objects.
This is just wrong. A pointer *is* a value. Its a memory address. STL
containers will work just fine with pointers.

Objects on the other hand must provide the required concepts as
mentioned before. The entire point of the STL is to provide a system
that allows for use with any custom type. They'd be pretty pointless
if they could only hold things like int, float, char* et al.

Workarounds exist but with 'Standard' STL there
always remains an 'impedance mismatch' when objects are used.
I'm not entirely certain what 'impedance mismatch' means. Although it
kinda reminds me of studying power amplifiers...

But the point that needs to be made here is that using smart pointers
in a container is not a work around. Smart pointers are a means to
perform resource control. In the case of using pointers, if the only
copy of a pointer to an object is in a std::vector, and then
std::vector::clear() is called, then the objects in it are leaked
(assuming we don't have copies to the pointer anywhere else). Smart
pointers do reference counting ( or some other method ) to determine
when an object should be delete'ed. So when std::vector::clear() is
called, the smart pointers can determine whether or not the object
should be delete'ed and thuse, no memory is leaked.
Best regards,
Roland Pibinger
HTH,
Paul Davis

Feb 17 '07 #5

P: n/a
On 17 Feb, 01:29, "paul.joseph.da...@gmail.com"
<paul.joseph.da...@gmail.comwrote:
On the other hand, if Roland meant that "You can't subclass objects
such as std::vector." then he is in fact correct. IIRC, most stl
objects don't provide a virtual destructor.
That doesn't stop me deriving from them.
#include <vector>
class foo : public std::vector<int{};

Nothing wrong there. The only thing I can't do without a virtual
destructor is delete polymorphically.

Whether deriving from standard containers is a good idea or not is a
different question, but there is certainly nothing that prevents it.

Gavin Deane

Feb 17 '07 #6

P: n/a
Gavin Deane wrote:
On 17 Feb, 01:29, "paul.joseph.da...@gmail.com"
<paul.joseph.da...@gmail.comwrote:
>On the other hand, if Roland meant that "You can't subclass objects
such as std::vector." then he is in fact correct. IIRC, most stl
objects don't provide a virtual destructor.

That doesn't stop me deriving from them.
#include <vector>
class foo : public std::vector<int{};

Nothing wrong there. The only thing I can't do without a virtual
destructor is delete polymorphically.

Whether deriving from standard containers is a good idea or not is a
different question, but there is certainly nothing that prevents it.
Except that, formally, an implementation of std::vector<that prevents
derivation (using a virtual base class trick getting) is standard
compliant. In practice, all implementations of the standard library allow
for derivation; and I do not hesitate to derive from standard container
classes whenever it feels appropriate. However, I do not see any blessing
for this technique in the standard. As far as I can tell, this would be a
compliant implementation:

namespace std {

class __protected_constructor {
protected:

__protected_constructor ( void ) {}

}; // protected_constructor

template < typename T, typename A >
class vector : private virtual __protected_constructor {

// ... do the vector business.

}; // vector

}
Best

Kai-Uwe Bux
Feb 17 '07 #7

P: n/a
On 16 Feb 2007 17:29:09 -0800, paul joseph wrote:
>On Feb 16, 1:05 pm, rpbg...@yahoo.com (Roland Pibinger) wrote:
>STL does not support object-oriented programming.

I think that this comment is misleading. If I understand the point of
the statement, its that using objects that use polymorphism in a
container isn't supported.
Just look at the containers, iterators and algorithms. No algorithm
works with (pointers to) objects (except random_shuffle).
>Because this isn't the case at all.
Although, objects used with the STL must provide certain concepts,
such as default constructibility, copy constructibility et al.
When dealing with class hierarchies, we must pay special attention to
copy constructibility and other concepts because these can lead to
problems such as slicing as noticed by the OP.
Objects (in the meaning used in object-oriented programing) are
characterized by identity, state and behavior. It makes no sense to
copy or assign objects. Copy constructibility makes only sense for
values and value-oriented libraries like STL.
>Using pointers is a perfectly valid method of fixing this issue.
If it needs fixing it must be broken.
>STL containers,
>iterators and algorithms are designed only for values, not for
(pointers to) objects.

This is just wrong. A pointer *is* a value. Its a memory address. STL
containers will work just fine with pointers.
A pointer is not a value, otherwise one could just use an int instead.
A pointer in C/C++ has the combined meaning of reference and address.
>Objects on the other hand must provide the required concepts as
mentioned before.
The 'required concepts' make sense only for values, not objects.
>The entire point of the STL is to provide a system
that allows for use with any custom type. They'd be pretty pointless
if they could only hold things like int, float, char* et al.
.... and 'concrete types' as Stroustrup calls them.
>Workarounds exist but with 'Standard' STL there
>always remains an 'impedance mismatch' when objects are used.

I'm not entirely certain what 'impedance mismatch' means. Although it
kinda reminds me of studying power amplifiers...
It means the mismatch that becomes evident when you try to use objects
with the value-based STL library.
>But the point that needs to be made here is that using smart pointers
in a container is not a work around. Smart pointers are a means to
perform resource control.
Since 'smart pointers' only try to imitate real pointers the
'impedance mismatch' is the same.

In general, STL is the attempt introduce the functional paradigm into
the C++ language as counterpart to the object-oriented paradigm. This
attempt has produced much misunderstanding and confusion.

Best wishes,
Roland Pibinger
Feb 17 '07 #8

P: n/a
* Kai-Uwe Bux:
>
... formally, an implementation of std::vector<that prevents
derivation (using a virtual base class trick getting) is standard
compliant.
Sorry, that's incorrect.

§17.3.1.2/1 "The library can be extended by a C++ program. ... Such
extensions are generally one of the following: ... Derived classes."

--
A: Because it messes up the order in which people normally read text.
Q: Why is it such a bad thing?
A: Top-posting.
Q: What is the most annoying thing on usenet and in e-mail?
Feb 17 '07 #9

P: n/a
On Feb 17, 1:12 pm, rpbg...@yahoo.com (Roland Pibinger) wrote:
On 16 Feb 2007 17:29:09 -0800, paul joseph wrote:
On Feb 16, 1:05 pm, rpbg...@yahoo.com (Roland Pibinger) wrote:
STL does not support object-oriented programming.
I think that this comment is misleading. If I understand the point of
the statement, its that using objects that use polymorphism in a
container isn't supported.

Just look at the containers, iterators and algorithms. No algorithm
works with (pointers to) objects (except random_shuffle).
This examples shows how to use std::sort on a std::vector or pointers.
As well as a trivial example of std::for_each to print the vector.

#include <iostream>
#include <vector>

class A
{
public:
A( int val )
{
_val = val ;
}

~A() {}

int
value()
{
return _val ;
}

private:

int _val ;
} ;

bool
compare( A* lhs, A* rhs )
{
return lhs->value() < rhs->value() ;
}

void
echo( A* a )
{
std::cout << a->value() << std::endl ;
}

int
main( int argc, char* argv[] )
{
std::vector< A* vec ;

for( int i = 10 ; i 0 ; i-- )
{
A* a = new A( i ) ;
vec.push_back( a ) ;
}

std::cout << "Before sort:" << std::endl ;
std::for_each( vec.begin(), vec.end(), echo ) ;

std::sort( vec.begin(), vec.end(), compare ) ;

std::cout << "After sort:" << std::endl ;
std::for_each( vec.begin(), vec.end(), echo ) ;
}
Because this isn't the case at all.
Although, objects used with the STL must provide certain concepts,
such as default constructibility, copy constructibility et al.
When dealing with class hierarchies, we must pay special attention to
copy constructibility and other concepts because these can lead to
problems such as slicing as noticed by the OP.

Objects (in the meaning used in object-oriented programing) are
characterized by identity, state and behavior. It makes no sense to
copy or assign objects. Copy constructibility makes only sense for
values and value-oriented libraries like STL.
You're right, wrong, and neither right or wrong. Of course objects are
characterized by their state and behavior. You're absolutely wrong
that it makes no sense to copy or assign objects, there are instances
where this may be true, but its just plain wrong to say never. I use
it quite a bit.

And the last bit that copy constructibility only makes sense in the
STL isn't quite right, although I don't tend to use it alot in my own
code, thats mostly becuase I don't write code that requires this
concept.
Using pointers is a perfectly valid method of fixing this issue.

If it needs fixing it must be broken.
STL containers,
iterators and algorithms are designed only for values, not for
(pointers to) objects.
This is just wrong. A pointer *is* a value. Its a memory address. STL
containers will work just fine with pointers.

A pointer is not a value, otherwise one could just use an int instead.
A pointer in C/C++ has the combined meaning of reference and address.
You can use an int for a pointer! (Disclaimer: Its very ill advised,
bad C++, and requires that an int be the same size as the pointer you
wish to obfuscate.)
Objects on the other hand must provide the required concepts as
mentioned before.

The 'required concepts' make sense only for values, not objects.
The entire point of the STL is to provide a system
that allows for use with any custom type. They'd be pretty pointless
if they could only hold things like int, float, char* et al.

... and 'concrete types' as Stroustrup calls them.
Workarounds exist but with 'Standard' STL there
always remains an 'impedance mismatch' when objects are used.
I'm not entirely certain what 'impedance mismatch' means. Although it
kinda reminds me of studying power amplifiers...

It means the mismatch that becomes evident when you try to use objects
with the value-based STL library.
But the point that needs to be made here is that using smart pointers
in a container is not a work around. Smart pointers are a means to
perform resource control.

Since 'smart pointers' only try to imitate real pointers the
'impedance mismatch' is the same.
I'm unsure as to how I should respond to this.

Yes, smart pointers only imitate real pointers. They are actually
objects that use a little voodoo to track the resources they own (The
underlying raw pointer). Because they are objects, they can be copied
and assigned. Writing code without smart pointers is ill-advised in my
opinion.

The only 'mismatch' that occurs with the objects used in the STL is
when the object doesn't support something required of it. The
algorithms in the STL were designed to work with any user defined type
as long as those types support a few basic operations. Obviously, if
something doesn't meet these requirements it won't work. You'll find
this happens alot when requirements aren't met.
In general, STL is the attempt introduce the functional paradigm into
the C++ language as counterpart to the object-oriented paradigm. This
attempt has produced much misunderstanding and confusion.
Obviously the STL can be misunderstood...
Best wishes,
Roland Pibinger

Feb 17 '07 #10

P: n/a
On Feb 17, 1:57 pm, "Alf P. Steinbach" <a...@start.nowrote:
* Kai-Uwe Bux:
... formally, an implementation of std::vector<that prevents
derivation (using a virtual base class trick getting) is standard
compliant.

Sorry, that's incorrect.

§17.3.1.2/1 "The library can be extended by a C++ program. ... Such
extensions are generally one of the following: ... Derived classes."

--
A: Because it messes up the order in which people normally read text.
Q: Why is it such a bad thing?
A: Top-posting.
Q: What is the most annoying thing on usenet and in e-mail?
Yeah, I was completely wrong on this point, as the following example
illustrates:

#include <iostream>
#include <vector>

template< typename TYPE >
class A : public std::vector<TYPE>
{
public:
A() {}
} ;

int
main( int argc, char* argv[] )
{
A<inta ;
a.push_back( 0 ) ;
std::cout << a.size() << std::endl ;
}

Feb 17 '07 #11

P: n/a
Alf P. Steinbach wrote:
* Kai-Uwe Bux:
>>
... formally, an implementation of std::vector<that prevents
derivation (using a virtual base class trick getting) is standard
compliant.

Sorry, that's incorrect.
No need to be sorry: if I was incorrect here, I would be quite happy.
§17.3.1.2/1 "The library can be extended by a C++ program. ... Such
extensions are generally one of the following: ... Derived classes."
You may be right (and I hope you are). However, I feel uneasy relying on
that clause alone.

a) Formally, the trick presented does not prevent derivation. It just
prevents construction of objects of the derived type:

namespace std {

class __protected_constructor {
protected:

__protected_constructor ( void ) {}

}; // protected_constructor

template < typename T, typename A >
class vector : private virtual __protected_constructor {

// ... do the vector business.

}; // vector

}

You still can do

class X : public std::vector<int{
}
you just cannot do

X x;

anymore. Where do you find a provision that classes derived from
std::vector<have to behave they way you want it to be? Without specific
guarantees that extensions are actually useful, the clause you quote
amounts to very little.
b) This is somewhat recognized in the part of the clause that you snipped:

The library can be extended by a C++ program. Each clause, as applicable,
describes the requirements that such extensions must meet. Such extensions
are generally one of the following:
? Template arguments
? Derived classes
? Containers, iterators, and/or algorithms that meet an interface convention

I read the sentence "Each clause, as applicable, describes the requirements
that such extensions must meet." as a hint that more specific provisions
are supposed to determine the semantics (behavior) of extensions. In the
absence of such provisions, I do not see how the standard places any
requirements on the behavior of a program extending the library. I.e., I
see a lot of undefined behavior. 17.3.1.2 in itself clearly does not say
how things are supposed to behave.
c) On the other hand, in favor of your reading, I can add that library
components such as

unary_function<>

which are clearly meant to be derived from, come without any hint whatsoever
that derivation is ok. However, the are other example, too: clause
[24.3.2/1] specifically blesses the use of std::iterator<as a base class.
d) Finally, a question: consider a type such as std::vector::iterator that
is labelled as implementation_defined, does the extendibility clause apply
to it, too? In that case, std::vector<T>::iterator could not be implemented
as T*.

Anyway, I would be _really_ _really_ happy if I was wrong and derivation
from standard containers was blessed by the standard. Also I think that (c)
is actually quite strong a point in your direction. But I think, the
standard could be more clear in this regard.

Thanks

Kai-Uwe Bux
Feb 17 '07 #12

P: n/a
* Kai-Uwe Bux:
Alf P. Steinbach wrote:
>* Kai-Uwe Bux:
>>... formally, an implementation of std::vector<that prevents
derivation (using a virtual base class trick getting) is standard
compliant.
Sorry, that's incorrect.

No need to be sorry: if I was incorrect here, I would be quite happy.
:-)

>§17.3.1.2/1 "The library can be extended by a C++ program. ... Such
extensions are generally one of the following: ... Derived classes."

You may be right (and I hope you are). However, I feel uneasy relying on
that clause alone.

[snip]
Without specific
guarantees that extensions are actually useful, the clause you quote
amounts to very little.
How would you define "useful"?

Anywayhow, I've argued successfully earlier that any program whatsoever
is a 100% standard-conforming C++ compiler, by the formally interpreted
rules of the standard. That's because the standard isn't a mathematical
document, but relies on the reader's common sense: it's formal in
places, but only insofar as formal definitions are practical and really
communicate something. So you can rejoice ;-), the standard does
specify, to the extent it can, that std::vector can be derived from.

--
A: Because it messes up the order in which people normally read text.
Q: Why is it such a bad thing?
A: Top-posting.
Q: What is the most annoying thing on usenet and in e-mail?
Feb 17 '07 #13

P: n/a
On Feb 18, 2:12 am, rpbg...@yahoo.com (Roland Pibinger) wrote:
On 16 Feb 2007 17:29:09 -0800, paul joseph wrote:
STL containers,
iterators and algorithms are designed only for values, not for
(pointers to) objects.
This is just wrong. A pointer *is* a value. Its a memory address. STL
containers will work just fine with pointers.

A pointer is not a value, otherwise one could just use an int instead.
A pointer in C/C++ has the combined meaning of reference and address.
What is your definition of 'value' that makes you say that a pointer
isn't a value? After all a pointer *is* just an integer, but one which
is interpreted in a specific way (old x86 style far pointers
notwithstanding), but that is the same as many other value types too.
In general, STL is the attempt introduce the functional paradigm into
the C++ language as counterpart to the object-oriented paradigm. This
attempt has produced much misunderstanding and confusion.
I've come across this assertion a couple of times. To me the STL is a
fine bit of OO programming, but I can see where the functional view
comes into it too.

The use of generic containers and the ability to perform operations no
them has been part of both functional languages and OO languages up
until early C++ and Java. What the STL doesn't do though is to enforce
the 'no side effect' rule from pure functional programming languages.
To me this puts it firmly on the OO side. It isn't really doing
anything that the containers in Smalltalk don't do and I'm not sure
that anybody would claim them to be a functional paradigm.
K

Feb 18 '07 #14

P: n/a
On 17 Feb 2007 12:30:46 -0800, "paul.joseph.davis" wrote:
>On Feb 17, 1:12 pm, rpbg...@yahoo.com (Roland Pibinger) wrote:
>Just look at the containers, iterators and algorithms. No algorithm
works with (pointers to) objects (except random_shuffle).

This examples shows how to use std::sort on a std::vector or pointers.
As well as a trivial example of std::for_each to print the vector.

#include <iostream>
#include <vector>

class A
{
public:
A( int val )
{
_val = val ;
}

~A() {}

int
value()
{
return _val ;
}

private:

int _val ;
} ;

bool
compare( A* lhs, A* rhs )
{
return lhs->value() < rhs->value() ;
}
This is the workaround. As said before no algorithm (except
random_shuffle) works with pointers out of the box.
>void
echo( A* a )
{
std::cout << a->value() << std::endl ;
}

int
main( int argc, char* argv[] )
{
std::vector< A* vec ;

for( int i = 10 ; i 0 ; i-- )
{
A* a = new A( i ) ;
vec.push_back( a ) ;
}
// compiles but wrong result
std::sort( vec.begin(), vec.end()) ;

// ditto; 2 dereferences needed to access the object
for (std::vector<A*>::iterator i = vec.begin(); i != vec.end(); ++i) {
std::cout << *i << std::endl;
}

const std::vector<A*>& const_vec = vec;
// changing pointed-to element in const vector
*const_vec[0] = 3;

// changing pointed-to element through const_iterator
// 2 dereferences needed to access the object.
**const_vec.begin() = 4;
std::cout << "Before sort:" << std::endl ;
std::for_each( vec.begin(), vec.end(), echo ) ;

std::sort( vec.begin(), vec.end(), compare ) ;

std::cout << "After sort:" << std::endl ;
std::for_each( vec.begin(), vec.end(), echo ) ;
// leaking objects
>}
>Objects (in the meaning used in object-oriented programing) are
characterized by identity, state and behavior. It makes no sense to
copy or assign objects. Copy constructibility makes only sense for
values and value-oriented libraries like STL.

You're right, wrong, and neither right or wrong. Of course objects are
characterized by their state and behavior. You're absolutely wrong
that it makes no sense to copy or assign objects, there are instances
where this may be true, but its just plain wrong to say never. I use
it quite a bit.
When identity is important (which is the case with objects) then
duplicate instances are always problematic (not to speak of
assignment).

Best wishes,
Roland Pibinger
Feb 18 '07 #15

P: n/a
On 17 Feb 2007 22:53:14 -0800, "=?iso-8859-1?q?Kirit_S=E6lensminde?="
<ki****************@gmail.comwrote:
>On Feb 18, 2:12 am, rpbg...@yahoo.com (Roland Pibinger) wrote:
>A pointer is not a value, otherwise one could just use an int instead.
A pointer in C/C++ has the combined meaning of reference and address.

What is your definition of 'value' that makes you say that a pointer
isn't a value? After all a pointer *is* just an integer, but one which
is interpreted in a specific way (old x86 style far pointers
notwithstanding), but that is the same as many other value types too.
A pointer can be dereferenced, i.e. pointers have a specific
dereference operator.
>In general, STL is the attempt introduce the functional paradigm into
the C++ language as counterpart to the object-oriented paradigm. This
attempt has produced much misunderstanding and confusion.

I've come across this assertion a couple of times. To me the STL is a
fine bit of OO programming, but I can see where the functional view
comes into it too.
OO is characterized by inherited and polymorphic objects. STL neither
uses nor supports these.
>The use of generic containers and the ability to perform operations no
them has been part of both functional languages and OO languages up
until early C++ and Java.
The term 'generic' doesn't tell you anything about the underying
paradigm.
>What the STL doesn't do though is to enforce
the 'no side effect' rule from pure functional programming languages.
STL is not pure functional. Otherwise sort, for_each and the other
'mutating' algorithms would have to return a list of immutable values.
But it is influenced by functional programming. The term 'generic' is
just a distraction in this context.
>To me this puts it firmly on the OO side.
Side effects don't necessarily mean OO :-)

Best wishes,
Roland Pibinger
Feb 18 '07 #16

P: n/a
Roland Pibinger wrote:
On 17 Feb 2007 22:53:14 -0800, "=?iso-8859-1?q?Kirit_S=E6lensminde?="
<ki****************@gmail.comwrote:
>>On Feb 18, 2:12 am, rpbg...@yahoo.com (Roland Pibinger) wrote:
>>A pointer is not a value, otherwise one could just use an int instead.
A pointer in C/C++ has the combined meaning of reference and address.

What is your definition of 'value' that makes you say that a pointer
isn't a value? After all a pointer *is* just an integer, but one which
is interpreted in a specific way (old x86 style far pointers
notwithstanding), but that is the same as many other value types too.

A pointer can be dereferenced, i.e. pointers have a specific
dereference operator.
>>In general, STL is the attempt introduce the functional paradigm into
the C++ language as counterpart to the object-oriented paradigm. This
attempt has produced much misunderstanding and confusion.

I've come across this assertion a couple of times. To me the STL is a
fine bit of OO programming, but I can see where the functional view
comes into it too.

OO is characterized by inherited and polymorphic objects. STL neither
uses nor supports these.
Hm, I always felt that this is simply because pointers are not really what
we want when dealing with objects. What we want is something like a
reference that can be assigned and re-seated. Something like this:

template < typename T >
class smart_ref {

T * the_ptr;

public:

// maybe, we should not have this constructor !
smart_ref ( T * ptr )
: the_ptr ( ptr )
{}

smart_ref ( T & ref )
: the_ptr ( &ref )
{}

operator T & ( void ) {
return ( *the_ptr );
}

operator T const & ( void ) const {
return ( *the_ptr );
}

// these really want to be overloaded dot-operators:
T * operator-( void ) {
return ( the_ptr );
}

T const * operator-( void ) const {
return ( the_ptr );
}

};

With this, STL works to some extend. The amount of failure derives mostly
from the fact that we cannot overload the dot-operator (which is a real
shame).
#include <vector>
#include <algorithm>
#include <iostream>
#include <string>
#include <ostream>

class X {

unsigned int the_ssn;

public:

X ( unsigned int ssn )
: the_ssn ( ssn )
{}

virtual
std::string name ( void ) const {
return ( "X" );
}

unsigned int ssn ( void ) const {
return ( the_ssn );
}

~X ( void ) {}

friend
bool operator< ( X const & lhs, X const & rhs ) {
return ( lhs.the_ssn < rhs.the_ssn );
}

};

struct Y : public X {

Y ( unsigned int ssn )
: X ( ssn )
{}

virtual
std::string name ( void ) const {
return ( "Y" );
}

virtual
~Y ( void ) {}

};

std::ostream & operator<< ( std::ostream & ostr,
X const & x ) {
return ( ostr << x.name() << "(" << x.ssn() << ")" );
}

typedef smart_ref<XX_ref;
typedef std::vector<X_refX_vect;

int main ( void ) {
{
X a ( 333451234 );
X b ( 919113247 );
Y c ( 238648666 );
Y d ( 237986136 );
X e ( 879823769 );
X_vect xv;
xv.push_back( X_ref(a) );
xv.push_back( X_ref(b) );
xv.push_back( X_ref(c) );
xv.push_back( X_ref(d) );
xv.push_back( X_ref(e) );
std::sort( xv.begin(), xv.end() );
for ( X_vect::const_iterator iter = xv.begin();
iter != xv.end(); ++iter ) {
std::cout << *iter << '\n';
}
}
}
Maybe, it's not that STL does not want to work with OO-objects. Maybe, it's
just that pointers make for lousy OO-objects.
Best

Kai-Uwe Bux
Feb 18 '07 #17

P: n/a
On Sun, 18 Feb 2007 09:31:59 -0500, Kai-Uwe Bux wrote:
>Hm, I always felt that this is simply because pointers are not really what
we want when dealing with objects. What we want is something like a
reference that can be assigned and re-seated. Something like this:

template < typename T >
class smart_ref {

T * the_ptr;

public:

// maybe, we should not have this constructor !
smart_ref ( T * ptr )
: the_ptr ( ptr )
{}

smart_ref ( T & ref )
: the_ptr ( &ref )
{}

operator T & ( void ) {
return ( *the_ptr );
}

operator T const & ( void ) const {
return ( *the_ptr );
}

// these really want to be overloaded dot-operators:
T * operator-( void ) {
return ( the_ptr );
}

T const * operator-( void ) const {
return ( the_ptr );
}

};

With this, STL works to some extend.
The problem with this approach is the automatic conversion from
pointer to reference (operator T&) which produces all kinds of
surprising results. BTW, Boost has a similar library (just for the
sake of completeness, not that I recommend Boost).
Moreover, this approach tackles the problem from the wrong direction.
Containers, iterators and algorithms need to become 'pointer-aware'.
This is not too difficult and has been done in the past.
>The amount of failure derives mostly
from the fact that we cannot overload the dot-operator (which is a real
shame).
IMO, pointers and references should be unified in a (hypothetical) new
C++. The result would be references similar (but not identical) to
Java.

Best wishes,
Roland Pibinger
Feb 18 '07 #18

P: n/a
On Feb 18, 7:03 pm, rpbg...@yahoo.com (Roland Pibinger) wrote:
On 17 Feb 2007 22:53:14 -0800, "=?iso-8859-1?q?Kirit_S=E6lensminde?="

<kirit.saelensmi...@gmail.comwrote:
On Feb 18, 2:12 am, rpbg...@yahoo.com (Roland Pibinger) wrote:
A pointer is not a value, otherwise one could just use an int instead.
A pointer in C/C++ has the combined meaning of reference and address.
What is your definition of 'value' that makes you say that a pointer
isn't a value? After all a pointer *is* just an integer, but one which
is interpreted in a specific way (old x86 style far pointers
notwithstanding), but that is the same as many other value types too.

A pointer can be dereferenced, i.e. pointers have a specific
dereference operator.
I still don't see how that stops it from being a value. Are you saying
that pointers don't follow value semantics because they can also be de-
referenced? In which case why is that relevant? Or are you saying they
do follow value semantics despite not being values?
>
In general, STL is the attempt introduce the functional paradigm into
the C++ language as counterpart to the object-oriented paradigm. This
attempt has produced much misunderstanding and confusion.
I've come across this assertion a couple of times. To me the STL is a
fine bit of OO programming, but I can see where the functional view
comes into it too.

OO is characterized by inherited and polymorphic objects. STL neither
uses nor supports these.
OO is characterised by encapsulated objects that have internal state,
are responsible for their own behaviour and communicate through
message passing. The STL does follow this. This newer definition of OO
centred around inheritance is a direct result of Java and to a lesser
extent C++, but it has no historic basis.

I've explained this in more detail no my web site:
http://www.kirit.com/The%20three%20p...%20Orientation
K

Feb 19 '07 #19

P: n/a
In article <11*********************@s48g2000cws.googlegroups. com>,
ki****************@gmail.com says...

[ ... ]
OO is characterized by inherited and polymorphic objects. STL neither
uses nor supports these.

OO is characterised by encapsulated objects that have internal state,
are responsible for their own behaviour and communicate through
message passing. The STL does follow this. This newer definition of OO
centred around inheritance is a direct result of Java and to a lesser
extent C++, but it has no historic basis.
I see little basis for this claim. Consider, for example:

Object-oriented programming is a method of implementation in
which programs are orgainzed as cooperative collections of
objects, each of which represents an instance of some class,
and whose classes are all members of a hierarchy of classes
united via inheritance relationships.

That's from _Object-Oriented Analysis and Design: With Applications
(Second Edition)_, Grady Booch, 1994. In the same book, use of objects
but not inheritance is titled "Object-based".

Going back even further:

A subclass specifies that its instances will be the same
as instances of another class, called its _superclass_,
except for the differences that are explicitly stated.
The Smalltalk-80 programmer always creates a new class as
a subclass of an existing class. A system class named
Object describes the similarity of all objects in the
system, so every class will at least be a subclass of
Object.

_Smalltalk-80: The Language_, Adele Goldberg and David Robson, 1989.

There is little or no historical support for the notion that use of
objects in the absence of inheritance gives object oriented programming.
The Standard Template Library was (and remains) largely template-based
-- but C++ was considered an object-oriented programming language long
before it supported templates at all.

--
Later,
Jerry.

The universe is a figment of its own imagination.
Feb 19 '07 #20

P: n/a
On 18 fév, 15:31, Kai-Uwe Bux <jkherci...@gmx.netwrote:
Hm, I always felt that this is simply because pointers are not really what
we want when dealing with objects. What we want is something like a
reference that can be assigned and re-seated. Something like this:
tr1::reference_wrapper? It will be incorporated in the next standard,
so let's use it (provided that those damn major compiler vendor gives
us a valid implementation of the tr1. As of today, it's quite hard to
use it in a portable way).

-- Emmanuel Deloget

Feb 19 '07 #21

P: n/a
On Feb 20, 1:40 am, Jerry Coffin <jcof...@taeus.comwrote:
In article <1171874692.373367.62...@s48g2000cws.googlegroups. com>,
kirit.saelensmi...@gmail.com says...

[ ... ]
OO is characterized by inherited and polymorphic objects. STL neither
uses nor supports these.
OO is characterised by encapsulated objects that have internal state,
are responsible for their own behaviour and communicate through
message passing. The STL does follow this. This newer definition of OO
centred around inheritance is a direct result of Java and to a lesser
extent C++, but it has no historic basis.

I see little basis for this claim. Consider, for example:

Object-oriented programming is a method of implementation in
which programs are orgainzed as cooperative collections of
objects, each of which represents an instance of some class,
and whose classes are all members of a hierarchy of classes
united via inheritance relationships.

That's from _Object-Oriented Analysis and Design: With Applications
(Second Edition)_, Grady Booch, 1994. In the same book, use of objects
but not inheritance is titled "Object-based".

Going back even further:

A subclass specifies that its instances will be the same
as instances of another class, called its _superclass_,
except for the differences that are explicitly stated.
The Smalltalk-80 programmer always creates a new class as
a subclass of an existing class. A system class named
Object describes the similarity of all objects in the
system, so every class will at least be a subclass of
Object.

_Smalltalk-80: The Language_, Adele Goldberg and David Robson, 1989.

There is little or no historical support for the notion that use of
objects in the absence of inheritance gives object oriented programming.
The Standard Template Library was (and remains) largely template-based
-- but C++ was considered an object-oriented programming language long
before it supported templates at all.
Yes and no. If you analyse how hierarchy is used in the languages
you'll notice that there are fundemental differences. In Smalltalk it
is not possible to use hierarchy for type checking so it is used for
programmer convenience.

If you look at the way that the collection classes in Smalltalk are
implemented you'll notice that they're conceptually similar to the
collection classes in the STL. Smalltalk's collections work with
objects that implement a specific capability/method/operator (which
ones depend on the collection class), not because they are a sub-class
of a specified super-class.

In as much as inheritance is used for type checking it has not been
important in older OO system. For helping the programmer to re-use
code and organise the system it has been important. These days most
people equate hierarchy with type checking and that is what I'm saying
isn't a defining quality of OO.

For what it's worth I think Alan Kay agrees with me:
http://userpage.fu-berlin.de/~ram/pu...doc_kay_oop_en
You'll notice that he never uses inheritance as part of his
definition.
K

Feb 20 '07 #22

This discussion thread is closed

Replies have been disabled for this discussion.