From mboxrd@z Thu Jan 1 00:00:00 1970 X-Spam-Checker-Version: SpamAssassin 3.4.4 (2020-01-24) on polar.synack.me X-Spam-Level: X-Spam-Status: No, score=-1.9 required=5.0 tests=BAYES_00 autolearn=ham autolearn_force=no version=3.4.4 X-Google-Language: ENGLISH,ASCII-7-bit X-Google-Thread: 1108a1,7a180be12347b9d3 X-Google-Attributes: gid1108a1,public X-Google-Thread: 103376,7a180be12347b9d3 X-Google-Attributes: gid103376,public X-Google-ArrivalTime: 2002-02-08 16:10:55 PST Path: archiver1.google.com!news1.google.com!sn-xit-02!sn-post-01!supernews.com!corp.supernews.com!not-for-mail From: "Matthew Heaney" Newsgroups: comp.lang.ada,comp.object Subject: Re: Merits of re-dispatching [LONG] Date: Fri, 8 Feb 2002 18:51:00 -0500 Organization: Posted via Supernews, http://www.supernews.com Message-ID: References: <3c62524f.93369796@News.CIS.DFN.DE> <1013094178.985786@master.nyc.kbcfp.com> <3c6392e8.2400843@News.CIS.DFN.DE> X-Priority: 3 X-MSMail-Priority: Normal X-Newsreader: Microsoft Outlook Express 5.50.4807.1700 X-MimeOLE: Produced By Microsoft MimeOLE V5.50.4910.0300 X-Complaints-To: newsabuse@supernews.com Xref: archiver1.google.com comp.lang.ada:19803 comp.object:33760 Date: 2002-02-08T18:51:00-05:00 List-Id: "Dmitry A. Kazakov" wrote in message news:3c6392e8.2400843@News.CIS.DFN.DE... > First C++ does not make any difference between class wide and specific > objects. The same type B is a class wide in B::f () and specific in > B::~B (). So the difference in how B::f and B::~B are dealing with > calls to g(). This is IMO bad. It's bad to the extent that it falsifies the programmer's mental model of how he thinks it should work. It violates the "principle of least astonishment." > Second. The behaviour of B::~B is safe. One should never expect > dispatching in a specific subroutine like destructor. My point is that > the language should prohibit dispatching from specific subroutines. > Therefore in my opinion the behaviour of B::f is unsafe. It is > declared as virtual (dispatching) which means that inside B::f the > type is already *known*. Thus there is no need in [re-]dispatching. A > call to g() can be statically resolved. Well, the programmer can turn off the dispatching: void B::f() { B::g(); //no dispatching } Here C++ and Ada95 diverge wrt syntactic overhead: in Ada95 you pay to turn dispatching on, and in C++ you pay to turn dispatching off. > The reason why C++ dispatches in B::f (), is that otherwise it would > impossible to have class wide subroutines [see the point 1]. In > contrary to this Ada 95 does have class wide routines, so my question, > why [explicit] re-dispatching is supported in Ada 95? Because you may want to let a derived type override the algorithm in the parent type. A class-wide operation typically declares an overall algorithm, and dispatching is used to provide the details: package P is type T is tagged limited null record; procedure Op1 (O : T); procedure Op2 (O : T); procedure Op (O : T'Class); end P; package body P is procedure Op (O : T'Class) is --static begin if then Op1 (O); --dynamic else Op2 (O); --dynamic end if; end Op; ... end P; This is fine, but if you want to change the algorithm used by class-wide operation Op, you can't. If you want to allow a derived type to replace the whole algorithm (not just the parts done by Op1 and Op2), then you have to make the operation primitive for the type, and then turn on the dispatching: package body P is procedure Op (O : T) is begin if then Op1 (T'Class (O)); else Op2 (T'Class (O)); end if; end Op; ... end P; Now a derived type (say, P.C.NT) can override Op. In general, an operation --primitive or class-wide-- should document which dispatching operations it calls, so that a derived type knows what is expected of it. This was the problem with your original example: you seemed to argue that it was some kind of language flaw in that you could call a dispatching operation in the Finalize operation. But this isn't bad because of any flaw in the language, this is bad because it's a dumb thing to do. The idiom for implementing a primitive Finalize operation is to finalize the specific type, and then call the Finalize operation of its parent. In particular, this means you shouldn't call any dispatching operations. In practice this isn't an issue, because operations are statically bound by default. If a Finalize operation does call dispatching operations, then of course this is a programmer error, no different from any other kind of programmer error.