From: francis_r on
Dear newsgroup readers,

When learning C++ I also studied Design Patterns because I figured that
if C++ is an object oriented language I better start thinking the
OO-way.

I soon discovered that C++ really is a combination of OO, functional
and generic programming. So I tried to expand my knowledge of these
paradigms by learning other programming languages. And indeed learning
Haskell really deepened my understanding of the STL (but I really miss
lambda expressions now). Learning Ruby opened my eyes to the usefulness
of iterators and each-loops (but I really miss closures now in C++).

When programming in C++ I see now many more ways to write my code and I
am left confused on how to proceed. With all these options available,
what is the C++ way?

Please share me your insights.

Kind regards,
Francis


[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

From: jk on
francis_r wrote:

> When programming in C++ I see now many more ways to write my code and I
> am left confused on how to proceed. With all these options available,
> what is the C++ way?

well in some stituations one or other technique usually stands out as
the way to do it, so you just rust your judgement and do it that way.
the tricky thing to realise is; if all options seem equally good, then
your intuition is probably right here too and any of them will do, so
just pick one (perhaps based on similarity to other parts of design)
and stop worrying about it. if all options seem equally bad thaen thats
usually a sign that you are missing something (either a pattern/idion
or perhaps something in the design).


[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

From: W. J. La Cholter on
"francis_r" <francis.rammeloo(a)gmail.com> wrote in
news:1154081437.672662.56150(a)m79g2000cwm.googlegroups.com:

> Dear newsgroup readers,
>
> When learning C++ I also studied Design Patterns because I figured that
> if C++ is an object oriented language I better start thinking the
> OO-way.

The Design Patterns book is a classic and fundamental for learning
good design and C++ development. Given its age, I would caution that
the example implementations do not represent best or good practices in
many current environments. For example, compare its Singleton with
that of Loki's.

> I soon discovered that C++ really is a combination of OO, functional
> and generic programming. So I tried to expand my knowledge of these
> paradigms by learning other programming languages. And indeed learning
> Haskell really deepened my understanding of the STL (but I really miss
> lambda expressions now).

Check out Boost Lambda.

>Learning Ruby opened my eyes to the usefulness
> of iterators and each-loops (but I really miss closures now in C++).
>
> When programming in C++ I see now many more ways to write my code and I
> am left confused on how to proceed. With all these options available,
> what is the C++ way?

It's a balance between the needs of your project and best practices
for your problem domain. Suppose you're developing a three-tiered
application, involving data, business logic, and presentation (such as
a typical web application). OO is a good way to implement the domain
objects in the business layer. The classes are easy to model and
translate into code. If there is commonality of operations, you might
choose some generic techniques (if nothing else, by using STL).
Hopefully, the data/business mapping layer can easily be mapped
orthogonally with a third-party mapper/serializer. A functional
approach could be best for the mapping because each mapping could be
represented as a transform. Likewise, some of the user-interface
presentation would be transform-dependent. On the other hand a
model-view-controller (MVC) framework has many OO aspects in its
implementation and interface.

Leveraging these techniques where appropriate is sound engineering.
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.

Some of the techniques are cutting edge, such as Boost Lambda.
Therefore, you need to balance whether your platform and those looking
at the code can support them. If you're building a GUI on a Microsoft
platform, and you have a requirement to support MFC instead of ATL,
you're stuck with its view of the world, circa 1997. No matter what
understand the current best practices because they can help you avoid
things like thread-unsafe singletons and brittle state machines.

[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

From: moleskyca1 on

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?

1 // all must inherit from here to be in a Collection
2 class Collectable
3 {
4 virtual int comp(const Collectable *, const Collectable *) = 0;
5 };
6 class Collection
7 {
8 public:
9 void add(Collectable *);
10 size_t size();
11 Collectable *getAt(size_t);
12 };
13 class Canvas; // forward declaration
14 class Shape: public Collectable
15 {
16 public:
17 virtual void draw(Canvas &) = 0;
18
19 };
20 class Canvas
21 {
22 public:
23 void render(Collection &sc) {
24 for ( size_t i = 0; i < sc.size(); i++ )
25 ((Shape *)sc.getAt(i))->draw(*this);
26 }
27 };
28 class Rectangle: public Shape
29 {
30 public:
31 void draw(Canvas &) {;} // override to draw rectangle
32 };
33 class Triangle: public Shape
34 {
35 public:
36 void draw(Canvas &) {;} // override to draw Triangle
37 };
38

I have some reasons, but I could benefit from more detail and stronger
reasons.


[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

From: Carl Barron on
<moleskyca1(a)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! ]

 |  Next  |  Last
Pages: 1 2
Prev: (Re) Constructing an object
Next: bind guard ?