Re: How to learn the C++ way?
<moleskyca1@yahoo.com> wrote:
Thank you for sharing, I have learned from this post.
W. J. La Cholter wrote:
For example, if you were to avoid generic practices for containers,
then you'd be stuck with something like pre-Java generics for
storing
a collection of objects. Perhaps, everything would have to inherit
from a common base class to be stored. If you try to use certain
generic algorithms without functional Boost Lambda (or C++ TR1's
implementation), you'd have to write ad-hoc functions to apply
transforms across objects that don't quite fit the interface.
If you
implement your domain objects using a functional technique, you
really
wouldn't have a three-tiered architecture anymore.
This part is very interesting to me. I still have argument with java
people about why is STL better than the pre-Java generics collection in
Java. As you say, everything must inherit from a base in order to be in
the collection. I know this is bad. Can you break it down for
beginner/intermediate like me and others I argue with? Here is some
pseudo-code (and C++ used to be like this pre-STL remember RougeWave
RWCollection?). Why is line 25 so bad? Why forcing inheritance from
Collectable is so bad?
[code snipped]
I have some reasons, but I could benefit from more detail and stronger
reasons.
It looks like you want a container of polymorphic Shape's. That said
I created a base class suitable for boost::intrusive_ptr as I have an
intruxive ptr with the same interface as boost's on this old compiler.
// Shapes.h
// forward declaration ok since we only use Canvas & in this header.
class Canvas;
class Shape
{
long count; // counter for reference counting
protected:
Shape(){} // prevent direct construction
public:
virtual void Draw(Canvas &) = 0;
virtual ~Shape(){} // so derived class's dtor is called
// functions for intrusive_ptr
friend void intrusive_ptr_add_ref(Shape *p) {++(p->count);}
friend void intrusive_ptr_release(Shape *p)
{
if(!--(p->count)) delete p;
}
};
class Rectangle:public Shape
{
public:
void Draw(Canvas &);
};
class Triangle:public Shape
{
public:
void Draw(Canvas &);
};
class Circle:public Shape
{
public:
void Draw(Canvas &);
};
// Collection.h
#include <list> // for a list container vector or deque also work.
#include "intrusive_ptr.h" // boost/intrusive_ptr.hpp in effect
#include "Shapes.h"
// namespace mine = boost;
typedef std::list< mine::intrusive_ptr<Shape> > Collection;
class Canvas
{
// simplest on this old compiler, various libs allow 'inline'
// creation of this
class render_one
{
Canvas &canvas;
public:
render_one(Canvas &a):canvas(a){}
void operator () (mine::intrusive_ptr<Shape> x)
{
x->Draw(canvas);
}
};
public:
void render(Collection &sc)
{
// walk the list
std::for_each
(
sc.begin(),
sc.end(),
render_one(*this)
);
}
};
this looks right and works if draw writes class name to std::cout.
[driver and the implementations not included above]
This looks like a safe implementation of a list of polymorphic objects.
and is probably more efficient than an imitation of JAVA code in C++.
I apologize if this was already in this thread...
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]