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! ]
|
|
0
|
|
|
|
Reply
|
francis.rammeloo (37)
|
7/28/2006 12:04:47 PM |
|
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! ]
|
|
0
|
|
|
|
Reply
|
jk
|
7/28/2006 1:18:33 PM
|
|
"francis_r" <francis.rammeloo@gmail.com> wrote in
news:1154081437.672662.56150@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! ]
|
|
0
|
|
|
|
Reply
|
W
|
7/28/2006 2:34:30 PM
|
|
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! ]
|
|
0
|
|
|
|
Reply
|
moleskyca1
|
7/28/2006 9:09:43 PM
|
|
<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! ]
|
|
0
|
|
|
|
Reply
|
cbarron3
|
7/30/2006 5:00:36 PM
|
|
moleskyca1@yahoo.com wrote in news:1154120006.944830.195500
@m73g2000cwd.googlegroups.com:
>
> 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);
The immediate answer is that the operation can fail for many different
reasons. There's nothing stopping the collection from holding
different types. In C++, without native garbage collection, you're
force to manage the item's destruction. You've also cluttered your
class hierarchy. If you wish to have a Shape play with other other
things, you need to add interfaces. Sun can get around this by
modifying java.lang.Object when they have the need to support new
features.
The theoretical answer is that Collection doesn't represent what you
want it to. It represents a collection of anything. Presumably, you
just want a collection of shapes. That could be represented as
std::vector<boost::shared_ptr<Shape> >. The shared_ptr is a safe way
to manage the object lifetime. If you want a collection of anything,
you could use std::vector<boost::any>.
> 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
C++ because it's multi-paradigm, is well suited for "say what you
mean" and "mean what you say." You can represent or model your
relationships, and clearly transform them into code. Being
"collectable" is orthogonal, or separate from a shape's having other
properties. Moreover, later on, if you wish to add more properties,
such as Renderable or Printable, you'd need have to hope the existing
interface suits your needs or you'd have to add an interface.
An interesting solution adopted in Java is the use of reflection to
implement orthogonal things like serialization or object-relational
mapping. In the old way, to make something persistent, you'd have it
derive from something like "Persistible." A better solution is
something like Hibernate, in which the bindings are defined
declaratively at run-time. That's preferable to mucking up a class
hierarchy, but injects dynamism that may not be necessary.
Another limitation to the above approach is that you cannot implement
something like the Non-Virtual Interface idiom (see other posts in the
group or C++ Coding Standards by Sutter and Alexandrescu): the
interface is public and the implementation uses private virtual
functions.
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
0
|
|
|
|
Reply
|
W
|
7/31/2006 8:46:57 PM
|
|
|
5 Replies
73 Views
(page loaded in 0.234 seconds)
Similiar Articles: How to remember key-bindings? - comp.emacsWell, you can redefine it in any way that you want, but by default, the ... the pattern >> C-<char> -> M-<char> for letters -> words) and then learn the >> exceptions. And C ... Invoke File-Aid Edit in Rexx - comp.lang.rexxInvoke File-Aid Edit in Rexx - comp.lang.rexx... then has the code above to call the panel, or c ... learning how to get around the way that ispf ... How to learn rpn mode for hp 50g - comp.sys.hp48Hi, How can I learn the rpn language for hp 50g? Thanks in advance. ... ... You will find that it's a far more natural way to compute. Dave To display a 3D skeleton, what do I need to learn? - comp.graphics ...HI I am a C programmer, I would like to learn ruby, rubycocoa and rubyOpenGL. ... scenes that respond to user interaction, then opengl is the way to go ... Is there a way to determine the host machine from within the local ...This is not a bad idea, but there needs to be a way to learn this information from the non-global zones themselves. Now that zones can be easily migrated from one server ... HP48GX Routine to Extract Prime Number Factors - comp.sys.hp48 ...... seems obvious to me that coding it in HPGCC is the way ... If one wants to use a specific exercise just to learn a specific category of programming (UserRPL, SysRPL, C, or ... Java Programmer Certification and Logo - comp.lang.java.programmer ...Speaking entirely for myself, I didn't learn enough from the course to write Java ... The paper is just a way to show it before you actually demonstrate it. What that ... Wildfire 5 intent manager - comp.cad.pro-engineerLearning pro/e when I did, there<BR>weren't so many automatic = features=20 and one had to learn how to sketch<BR>in a way to obtain the desired=20 shape.<BR><BR>I ... comp.lang.tcl - page 4C API list manipulation - sort -uniqe? 1 91 (11/27/2009 12:54:32 PM) Hi, I am trying to learn the 8.4 C API and I have a question about handling lists. I like the way ... how to get ascii data in the hp 50g with the seriell port and ...Is there any way to connect the hp 50g with a surveying instrument and get ... problems: what cable i have to use? how i can get the data without learning sysrpl... . c and ... How to Learn C++ | eHow.comThe Best Way to Learn Excel Software. Microsoft Excel is spreadsheet computer ... Learn to play the C Sharp Major and C Sharp Minor chords on the piano in this free how ... Learn Code The Hard Way -- Books And Courses To Learn To CodeLearn Python The Hard Way. Downloaded more than 500 thousand times, Learn Python The Hard Way is proving to be an effective and fun book for learning to ... 7/14/2012 3:04:01 PM
|