POV-Ray : Newsgroups : povray.general : CSDL: C-like Simulation Description Language : Re: CSDL alpha 1 release Server Time
7 Aug 2024 07:14:42 EDT (-0400)
  Re: CSDL alpha 1 release  
From: Warp
Date: 23 Jan 2002 18:57:16
Message: <3c4f4ddc@news.povray.org>
Christopher James Huff <chr### [at] maccom> wrote:
: And how else am I supposed to get a copy?

  Needing to do this with just mere base class pointers is clear sign that
you haven't designed your object hierarchy well.

  For example in our project I have implemented a bitvector which has some
functionalities needed in our libraries that std::vector<bool> doesn't have,
and which implements the copy-on-write technique for efficiency (these
bitvectors are copied a lot and modified very seldom). (If you don't know
what the copy-on-write technique means, just ask.)
  It either allocates the bit array dynamically or uses a user-given memory
location (kind-of placement new functionality).
  Of course this is a very different situation than yours, but now I'm getting
to my point: Things are allocated dynamically, copied, freed and so on, but
all inside the bitvector class. The bitvector handles everything.
  From outside I only need to use instances of this bitvector. I can assign
this bitvector, give it as a value parameter, return it by value, everything
that can be done by value (ie, no pointers) and it still is efficient, no
matter how large the bitvector is. It itself takes care of everything related
to pointer and dynamic allocation *inside* itself, privately. I don't see what
it does from outside, and I don't even want to see it.
  That's the whole point of modularity.

  One of the main principles of modularity is that if a module reserves a
resource (eg. memory), the same module (moreover, with just a few exceptions,
the same instance of the module which made the allocation) takes care of
freeing this resource and that no leaks happen.
  A module which allocates a resource and then returns a handle to this
resource to the outside, to the upper level and *hopes* that it gets freed
somewhere else, is almost always a sign of a really, really bad module design.

  Designing a good, working and secure object hierarchy is not something to
be done lightly, not even in medium to small sized programs. If you make
a good design, you'll gain a lot later.

:> : Having to return void pointers and cast them to the 
:> : correct types.
:>   I never have to do this. It also breaks badly modular OO design.

: Which is why I don't like it.

  One of the reasons why so many people love Java and hate C++ is that
Java simply doesn't support "bad" features from C, while C++ does (for
compatibility). Usually people who learn C++ come from C, where they learnt
really bad habits, which they can't get rid of in C++ for long, long time
(unless they have very good teachers). The good thing in Java is that it just
doesn't have these bad ways of doing things, so you just can't use them.
  Personally I dislike Java because in my opinion it has gone just way too
far with its limitation of "bad" features (which really aren't). Java has
many good things, and many of the limitations are things that I don't really
miss (eg. "kludgy" pointer casts), but on the other hand it misses things
that are really useful in C++ and helps a lot in implementing modularity
(even though some of these things *might* be possible to use in a wrong way,
I don't, so removing them is a true limitation to me).

: In C++, if you have a derived object that implements a certain method 
: not in its base class, but only have a base-class pointer to it, you 
: can't call that method unless you cast to that type.

  I don't want to sound rude, but you should really study object orientedness
principles in more detail.
  In an object-oriented hierarchy a module/function which takes a base class
reference/pointer is only interested in the base class interface. It does
not know, and moreover it doesn't even want to know, if there's really a
derived class behind that reference or pointer. It just sees a base class
and period (the derived class *is a* base class by all practical means); it's
not interested in anything else.
  If this kind of module/function needs to know more, it's usually a sign
of bad OO design.

: I've been avoiding using references

  Bad idea. You should really use references instead of pointers whenever
possible (and *const* references whenever possible).
  It's much easier to shoot yourself in the foot with pointers than with
references.
  It's not a syntax thing (syntax is usually the least of your worries). It's
a higher level thing.

: And I have to use dynamic allocation because the objects are going to 
: stick around for an indefinite amount of time, they can't be deleted 
: when the function goes out of scope.

  That's where you should make a module (ie a class) to handle this and not
just leave the pointers float around and hope that they will sometime be
freed by something. That sounds a lot like what you want to do is a
container class (ie. a class that contains objects and takes care of creating
and destroying them).

:> : Templates.
:> 
:>   What about them?

: They make my head hurt. ;-)

  Templates are incredibly versatile. In fact, it has been proven that
templates (with C++ types) alone are a turing-strong language. You can
make loops, lists, trees, conditionals, etc. which are evaluated at
compilation time (ie. you can, for example, make a list of constant int
values, add values at the end of the list, remove values from the list,
join lists, traverse a list etc, all at compilation time).
  (This is actually a whole field of research, called "generative
programming".)

  Templates have saved me a lot of work in many places.

: They're fine unless there's a problem. If there's a problem, it's often 
: very difficult to figure out what it is from the error messages.

  Templates have their problems, and error messages are one of them (the
other is that no compiler yet has implemented export templates, which means
that your object files will be HUGE if you use lots of big templates).
  However, you get used to them with experience. (Also with experience you
just usually avoid the error messages completely :P )

-- 
#macro M(A,N,D,L)plane{-z,-9pigment{mandel L*9translate N color_map{[0rgb x]
[1rgb 9]}scale<D,D*3D>*1e3}rotate y*A*8}#end M(-3<1.206434.28623>70,7)M(
-1<.7438.1795>1,20)M(1<.77595.13699>30,20)M(3<.75923.07145>80,99)// - Warp -


Post a reply to this message

Copyright 2003-2023 Persistence of Vision Raytracer Pty. Ltd.