As part of a private followup discussion adrianh@cogs.susx.ac.uk asked
me a question whose answer I thought might be of more general interest:
> I would be interested to know what you consider the major strengths of
> C++ to be over Pop-11+ObjectClass for example (with the exception of
> speed of course :-)
A small wish-list (if any of these are already in objectclass, I'd like
to know - I'm not sure what the latest version is).
1) Virtual/non-virtual base classes. This means that when you have
multiple inheritance so that the same "grandparent" is inherited by two
or more different routes, you can specify whether you get one copy of it
or several. It's hard to make a realistic small example, and of course
you don't "need" this distinction (any more than you "need" multiple
inheritance). The best I can think of, off the top of my head, is a
graphical object which has a position and a colour. If you make a new
type of graphical object which inherits from two other types of
graphical object, you might want it to have one position and two
colours, or two positions and one colour, or one position and one colour
(the objectclass behaviour). For example, a coloured rectangular border
"mixin" might want to share size and position with some other
rectangular object, but have its own colour. With the
virtual/non-virtual distinction, you wouldn't need to inherit from a
new, separate "mixin" class - you could inherit from an ordinary
unfilled rectangle, and tell it not to have its own copy of size and
position but to share its size and position with the thing it was mixed
into. You would then get an ambiguity if you tried to access the
colourof the resulting object, unless you specified whether you wanted
the colour of the border or the colour of the other inherited object, or
wrote a new colourof function.
2) Non-virtual member functions (methods) (these are not the same as
static member functions - which are like class variables). These look
like a restriction, because you can't mess with them in a derived class.
They are probably as irritating as using top-level lvars in a library in
pop11, but enable the class library programmer to write secure code
which the person using the library can't screw up. I think they are a
cleaner way to do it than the pop11 way.
3) Type checking. I wish pop11 had the *option* of type declarations.
They are a real pain a lot of the time, but are nice to have if you want
it. I like the CL/CLOS approach: optional type declarations which can
either be used for type-checking at run-time or to produce faster code
depending on your compiler settings. (Of course, in C++ you get
type-checkign at compile time *and* faster code -- but at the cost that
they are not optional.)
4) The public/private inheritance distinction. Another artificial
example: if you wanted to implement a stack class built on an array
class, you could use private inheritance: the array is inherited for
implementation, but a stack is not an array. Public inheritance implies
an ako relationship between the classes.
5) This is like (2) above, different public/protected/private access to
data members (instance variables) and member functions of a class. You
don't need to protect your users from accessing classes in the wrong way
- but it is a good idea for writing safe, maintainable code. Sections
are at the wrong level of granularity (and I don't like sections
anyway.)
6) Destructors. I like having constructors and destructors for objects.
Of course with a GC language objects tend to have a longer lifetime than
when they are allocated on the stack, but I think it is conceptually
cleaner to, say, close a file in the destructor of an object which
opened and accessed the file. In pop11 you would use a mixture of exit
actions for short term access, and "after gc" actions for long-lived
objects.
7) Stack objects. I *really* like the idea of allocating objects as
local variables (on the stack) rather than having a local variable whose
value is a heap object. Stack objects mean that you can do a lot of
complicated stuff without creating garbage - and you can do it easily.
Most of the above points can be taken separately, even (7) doesn't
really need any type declaration, just some new syntax, e.g.
lvars_conswith {% a, b, c %} foo; would create a three element vector
"foo" initialised with the values of the variables "a", "b" and "c".
Maybe in the next-but-one major version of Poplog??
--jlc
p.s.
A disadvantage of stack-allocated objects is that you can do a lot
more copying of objects if you are not careful. I don't think this would
happen in pop11, because parameters in pop11 are passed in a way which
is like C++ references, rather than by value. And one common C++ bug -
returning a reference to a stack object instead of returning the object
(which results in it being copied) needn't happen in pop11 because it
already has mechanisms for coping with access to lexicals after their
stack-frame has vanished.
|