From: pete@borland.com (Pete Becker)
Subject: Re: Borland's design decisions
Organization: Borland International
Date: Thu, 16 Apr 1992 00:13:29 GMT

In article <1992Apr14.191015.29216@ucc.su.OZ.AU> maxtal@extro.ucc.su.OZ.AU (Tim Lister) writes:
>In article <1992Apr8.003300.20919@borland.com> pete@borland.com (Pete Becker) writes:
>>In article <1992Apr2.131624.245@pictel.com> boba@pictel.com (Bob Alexander) writes:
>>>Secondly, Borland extended C++ with dynamic dispatch virtual tables.  Why?
>>>Why not just just create virtual member functions like WMLButtonDown that
>>>always receive a particular message and that the user can override?  What
>>>do DDVTs add that is so worthwhile as to justify a non-standard extension
>>>to C++?
>>>
>>
>>	You could create a base class that responded to every possible Windows
>>message, but you'd have to provide 64K identical functions, each calling
>>DefWindowProc().  Then your derived class could override the ones that were
>>appropriate.  Now you've got two rather large vtables...
>>	-- Pete
>>
>Pete, IMHO your explanation is inadequate. I have a window management 
>mechanism that handles messages and doesn't use DDVTs or 64K.

	The original question asked about "creating virtual member functions",
the implication being that there would be some base class that would handle
everything you throw at it.  I, too, have a window management mechanism that
doesn't use DDVTs or 64K.  See the TODO example that we ship.  But exposing
that much of the implementation doesn't seem to me like good design.

>The method:
> 1) define a basic class with say messages 1-10 decoded by a switch
>    and calling 10 virtual functions. All other messages go to
>    MyDefWinProc, which is virtual. All these virtuals call DefWindowProc().
> 2) Just use it. Now wait, you want to use message 11?
>    OK, two methods:
>    a) Override MyDefWinProc to filter out message 11, else call 
>       immediate base class version of MyDefWinProc.
>    b) Same as above, but instead of doing it on the fly, package it
>       away for reuse.
>
>In effect, this does the same as a DDVT, but the code is written in C++
>not 8086 assembler. It is not as fast, requires more user support,
>won't work with existing windows etc, but it doesn't require
>any non-standard language, and it doesn't require 64K.

	Incidentally (loaded question follows), can anyone anywhere honestly
say that they've ever written a Windows program in ANSI C or C++?
Remember, int WinMain( whatever ) disqualifies you right from the start.
	The true issue here is whether this extension is worthwhile.  Of
course there are other ways that message numbers can be mapped to member
function calls.  In order to assess them, you have to look at how intrusive
they are on the user, as well as how big and how fast they are.

>
>I ask for opinions on Borlands language extension.
>Pete, perhaps you might post a proper explanation of the syntax and its
>purpose for those not using BC.

	class Demo
	{
	virtual void f() = [firstMessageNumber];
	void dispatch( int msgNum );
	virtual void defaultAction();
	};

	class DerivedDemo : public Demo
	{
	virtual void g() = [secondMessageNumber];
	};

	Calling dispatch( n ) will call the virtual function whose dispatch
number equals 'n', regardless of which derived class defines it.  If no class
provides a virtual function whose dispatch number equals 'n', defaultAction()
is called.  Note: this is illustrative only.  The actual code is buried in an
assembler module somewhere, and I agree that that needs to be changed.
	The most direct way to do this is C++ is to write a class that maps
dispatch numbers to member function pointers, which is what's done in MFC.  One
drawback in using this approach is that the code to register each function
is not part of the class definition, so you can't tell from reading the
definition which functions map to which messages.
	-- Pete