> I could imagine a future situation in which a "lazy" C++ programmer
> wrote a library using dynamic typing, but a smart compiler optimised
> it to static typing
I think Jonathan may be over-estimating what the C++ proposal will do.
It will not support dynamic typing in the same way as Pop: the idea is
to retype a pointer if it is safe to do so, otherwise return a null.
To illustrate, suppose we have a simple hierarchy
class foo { // note that foo has no parents
public :
int a;
};
class baz : public foo {
public :
float b;
};
foo *quum; // a pointer to a foo object - or is it to a baz object?
and suppose we wanted to print whatever quum is pointing at. A simple
way of doing this would be to declare a print() member function in
each class, making it virtual so that the object knows to check its
virtual method table to find out its class (actually a C++ programmer
would use streams, but that's not relevant here)
class foo { // note that foo has no parents
public :
int a;
virtual void print();
};
class baz : public foo {
public :
float b;
virtual void print();
};
foo *quum; // a pointer to a foo object - or is it to a baz object?
void test()
{
quum->print(); // selects the right definition
}
But suppose we don't have the source, and so can't change the class
definitions. With the extensions, we could define test() as
void test()
{
if (baz *ribbet = dynamic_cast<baz *> quum)
cout << (ribbet->a) << (ribbet->b);
else
cout << (quum->a);
}
But if you try to to a dynamic_cast to a class that is not a child of
the pointer you supply, you will get a compile-time error, not a
run-time error as in "soft" languages such as Smalltalk. Thus "lazy"
programmers will not really find this helping them (and thank goodness
for that say I - one of the ideas behind "hard" languages is to
minimise the number of run-time errors in code that has been deliverd
to a customer, and "soft" retyping would remove this safety).
This example was perhaps a little contrived. One of the other reasons
for introducing this feature into the language was that there are a
large number of C++ class libraries which have been directly ported
from Smalltalk (eg. NIH) or other soft languages (eg. Actor originated
the Borland Windows library). These have single hierarchies based on a
class such as TObject, and utility classes such as TList store
pointers to TObject, even though what you put in is pointer to a
descendant class. To work out what to do with an extracted object one
writes a virtual function IsA(TObject &), which typically relies on a
string comparison based on a class string variable holding the name of
the class. The programmer then does a cast on to the identified type.
This is clearly inefficient (because the necessary information is more
quickly available from the object's pointer to its virtual method
table), and less safe (because the C cast makes no guarantee that the
pointer generated is type compatible). (*)
This sort of contortion is usually unnecessary (Stroustrup suggests
alternatives which are also more efficient), but are common and
sometimes cannot be avoided. The new dynamic cast allows a safe and
efficient method of doing this, but presumably at the cost of
associating a pointer to a virtual method table for each object even
if its class definition defines no virtual member functions.
Conclusion - soft languages may adopt some of the hard language
techniques for compile-time optimisation, but I can't see hard
languages adopting general-purpose dynamic typing because it would
compromise some of their design goals.
Scott Wheeler
(*) This sort of thing is usually done by the people who present
papers at conferences saying how they want full dynamic typing,
garbage collection, and a set of standard functions (such as print()
and IsA()) added to every class added to C++. I never understand why
they don't just use Smalltalk - it would be far more usable than C++
in drag.
|