Path: utzoo!news-server.csri.toronto.edu!cs.utexas.edu!sun-barr!lll-winken!elroy.jpl.nasa.gov!sdd.hp.com!mips!daver!tscs!tct!chip From: chip@tct.uucp (Chip Salzenberg) Newsgroups: comp.std.c++ Subject: Re: Overloading vs. virtual functions Message-ID: <27D2986D.33CD@tct.uucp> Date: 4 Mar 91 18:56:45 GMT References: <1991Feb25.201923.14554@gpu.utcs.utoronto.ca> <27CD13BF.64D1@tct.uucp> <1991Mar3.003937.17389@gpu.utcs.utoronto.ca> Organization: Teltronics/TCT, Sarasota, FL Lines: 121 According to craig@gpu.utcs.utoronto.ca (Craig Hubley): >I am describing a situation in which the decision which of two functions >is called is visible to the producer but invisible to the consumer. But, you see, the consumer needs to know! The consumer is a C++ programmer who is presumably conversant with "Base& b = d" and other type-related features. That programmer wants and needs to know which member functions are dependent on the dynamic type of an object and which are not -- i.e. which are virtual and which aren't. >Having the decision which function to call made at compile-time or >run-time changes nothing. It matters a great deal if the dynamic and static types disagree. >>Constant expression folding was state-of-the-art in >>the 60's, and it has zero relevance to OOP typing issues. > >It has lots of relevance to efficiency ... I've been persuaded that the ClassID feature would have little impact on efficiency. >>overriding both static and dynamic typing. But I confess that I the >>relevance of this language feature to a supposed conflict between >>overloading and virtual functions escapes me. > >Getting [static and dynamic typing] to work together to provide consistent >behavior can be very clumsy. Especially when the compilers obey different >sets of rules... I don't think they _can_ provide consistent behavior. If two mechanisms have distinct existence purely because of their differences, then making them alike make the distinction between them redundant. Consider the application of this rule to dynamic and static typing, i.e. virtual and non-virtual functions. >>In the absence of other considerations, I would suggest that the >>overloading of the virtual function be subsumed into an overloaded >>constructor (or non-member function), and that the constructed object >>(or function return value) be used as an actual parameter of the >>no-longer-overloaded virtual function. > >In other words, conversion ? Not necessarily. I refer to explicit constructor calls that may have more than one argument. For example, let us consider class C constructed with an overloaded virtual function a la Hubley: class C { virtual void larry(int, int); virtual void larry(long, long); }; In the Salzenberg variation, this becomes: class L { // abstract superclass virtual void larry() = 0; }; class INT_L : public L { INT_L(int init_i, int init_j) { i = init_i; j = init_j; } virtual void larry(); private: int i, j; }; class C { virtual void larry(const L&); }; In this scheme, INT_L handles what used to be "larry(int,int)". Expansion of the the larry() feature to new argument list involves creation of one new class derived from L, one or more constructors for that class, and one new version of L::larry(). Surely this is a better choice than introducing yet another overloaded larry() function which then must be implemented in all subclasses of C. (Unless, of course, the inheritance tree rooted at C is very shallow.) >Now how can you claim that A.overloads/B.virtuals/C.conversion have >nothing to do with each other when you have transformed code >using A,B into code using B,C without affecting functionality at all? The fact that an algorithm that uses an old feature set can be recast using a new feature set does not imply that the new feature set is in all ways equivalent to the old. >You are displaying clearly that they are all ways of accomplishing the >*same* thing, which is my point exactly. Yes, well, so is assembler, if you define "same thing" broadly enough. >If all I am doing is printing out the date, I MAY NOT WANT the datestring >char* to be converted to a Date so I can print it out again - talk about >overhead! Using the above example, the L class not cause any conversions whatsoever until they are needed. The concept is rather like those tiny classes returned by typical "operator[]" functions: they don't actually _do_ anything until assigned to or accessed or whatever. >You are arguing FOR a form of "control" (exact type matching) that only >affects your own source code, but AGAINST a form of "control" (convertible >type matching) that can drastically improve runtime efficiency. If you would be so kind as to give a reasonably complete definition of "convertible type matching," I would be obliged. (Unless it refers to the freedom to modify virtual function definitions in ways that can be adapted for using automatic type conversions; I understand that, and I consider it unimportant.) >The "difference of techniques" you cite is not a difference of techniques >at all but rather a difference of syntax only ... Surely you don't mean that virtual functions and non-virtual functions differ only in syntax. What _do_ you mean? >C++ prefers to match derived-type functions with all rules at its disposal >FIRST, before trying to match base-type functions at all. Of course.