[net.lang.c++] New C++ Release

bs@alice.UucP (Bjarne Stroustrup) (07/08/86)

Release 1.1 of the C++ translator is now being shipped.

As promised, 1.1 primarily represents a quality improvement over release 1.0
and provides no major language extensions. It is, of course, compatible.

1.1 runs faster, uses less memory, generates better code, has fewer ``sorry
not implemented'' messages, detects more errors, gives better error messages,
is more portable, and has fewer bugs than 1.0.

The performance improvements are measurable but not dramatic.
The ``language recognition and error handling'' quality improvements
are noticeable.

Almost all bugs reported on the net, to me, or to AT&T as of June 1 are fixed.

Internally, the most extensive changes are the handling constructors of the
form X(X&), handling of destructors, handling of pointer to functions,
handling of ``const'', error and ambiguity detection for overloaded functions,
memory allocation (1.1 uses malloc, not break), and some aspects of error
handling.

1.1 does provide two language extensions:
	- pointers to members
	- protected members
I don't consider them major, but for some styles of programming they are
significant. The problems these extensions are designed to cope with have
been known for years, but only recently did I find suitable solutions.
I'm trying to keep C++ an evolving language without getting into
incompatibilities or creeping featurism. This is not easy.

The two new features are documented in the 1.1 release notes.

As far as I know, the price of 1.1 is the same as for 1.0 ($250 for educational
institutions and $2000 for commercial firms for source). If you already have a
commercial license for 1.0 you get 1.1 for $400.

The PC versions of C++ sold by Oasys are based on Release 1.1.

As usual, the translator comes for AT&T 3Bs or VAXs running SysV or BSD.

Release 1.1 includes a ``porting kit''. It is easier to port than 1.0.

There is a new compiler option: +e.
	``CC +e1'' causes virtual tables to be external and defined
		(that is, initialized).
	``CC +e0'' causes virtual tables to be external and only declared
		(that is, uninitialized).
	``CC'' causes  virtual tables to be local to a file (static) and defined
		(as always in 1.0).
Using +e you can optimize a program by ensuring that only one virtual table per
class is generated. This can save 25% of .o size, a.out size, link time, and
(in case of cross compilation) download time. If you don't use it everything
remains as it was with 1.0: +e is a pure optimization.

Pointers to Members:

	As mentioned in the C++ book (page 153) there was no proper way of
	declaring and using pointers to member functions. This has been fixed
	(and the word ``Sorry'' was removed in the second printing).

	Consider:
		struct s {
			// ...
			int mf(char*);
		};
	How do you declare a pointer to a member function such as ``s::mf''?
	How do you call a function through such a pointer?

	A pointer to member function is declared just like any other pointer
	to function except that it must be explicitly stated that the pointer
	is to a member of a specific class. ``s::*'' means ``pointer to member
	of class s''. For example:
		int (s::*pmf)(char*) = &s::mf;
	Since ``pmf'' points to a member function and since a member function
	must be called for a specific object an object must be supplied in a
	call (in addition arguments required by the member function):
		s obj;
		int i = (obj.*pmf)("some string");
		s* p = &obj;
		i = (p->*pmf)("another string");
	The parentheses around the .* and ->* expressions are necessary because
	of the standard C++ operator binding rules
		i = p->*pmf("another string");
	means
		i = p->*(pmf("another string"));
	and that is an error.

	It is possible to take the address of a virtual function and assign
	it to a pointer to member function. In that case the actual function
	is found at the time of each call through the pointer dependent on
	the object it is called for.

		struct b {
			virtual void f() { printf("base"); }
		};

		void (b::* pvf)() = &b::f;

		struct d : b {
			void f() { printf("derived"); }
		};

		d a;
		b* p = &a;

		main() {
			(p->*pvf)();
		}

	Will print ``derived'' (not ``base'').


Protected Members:

	The basic scheme for separating the (public) user interface from
	the (private) implementation details has worked out very well for
	data abstraction uses of C++. It matches the idea that a type is a
	black box. It has proven to be less than ideal for object-oriented
	uses.

	The problem is that a class defined to be part of a class hierarchy
	is not simply a black box. It is often primarily a building block for
	the design of other classes. In this case the simple binary choice
	public/private can be constraining. A third alternative is needed:
	A member should be private as far as functions outside the class
	hierarchy are concerned but accessible to member functions of a
	derived class in the same way that it is accessible to members of
	its own class. Such a member is said to be ``protected''.

	For example, consider a class ``node'' for some kind of tree:
		class node {
    			// private stuff
		protected:
			node* left;
			node* right;
			// more protected stuff
		public:
			virtual void print();
			// more public stuff
		};
	The pointers ``left'' and ``right'' are inaccessible to the general
	user but any member function of a class derived from class ``node''
	can manipulate the tree without overhead or inconvenience.

	A related change is that you can now also use ``private'' labels
	in a class in the same way as you can have ``public'' and ``protected''
	labels:
		struct my_type {
			// public interface
		private:
			// private stuff
		};

mitch@well.UUCP (Mitchell Waite) (07/11/86)

I understand that this might be a late
point to ask this question, but I was
wondering if you could elaborate just a
bit about what C++ offers over regular C
and if you think many C programmers will
be moving towards C++.  I have not found
a single article that really compares
the two langauges in a simple way.  I
hope this is not too much to ask.