Path: utzoo!utgpu!news-server.csri.toronto.edu!cs.utexas.edu!wuarchive!uunet!microsoft!jimad From: jimad@microsoft.UUCP (Jim ADCOCK) Newsgroups: comp.std.c++ Subject: Re: Dynamic Binding by Argument Type Message-ID: <70652@microsoft.UUCP> Date: 13 Feb 91 19:50:44 GMT References: <2715@meaddata.meaddata.com> Reply-To: jimad@microsoft.UUCP (Jim ADCOCK) Organization: Microsoft Corp., Redmond WA Lines: 101 In article <2715@meaddata.meaddata.com> johnt@meaddata.com (John Townsend) writes: .... >Why is it that *b1 is treated as a Derived object when it is the invoking >object, but as a Base object when it is the argument? Is this intentional? I believe this design choice was intentional. If one generalizes g() to n parameters you get n-dimensional dispatch: g(x, y, z) where if x, y, and z can each be one of 20 classes would be selecting a particular g() out of 8000 possible choices. This could be done --but its hard to imagine compiler schemes to automatically handle these requirements, and simultaneously be relatively efficient of excutable time and space. Simple, fast, techniques are readily available to do one dimensional dispatch, and that's where C++ draws the line. In your case, where g(ob) is itself a member, you'd be in general asking for 2D dispatch, g(ob1, ob2) would be 3D dispatch .... Obviously, people would not typically overload all 8000 functions mentioned above. Thus, we'd have to figure out a new set of rules as to which of the previously defined functions are suppose to be called. The rules for picking the "closest match" function in N-dimensions are not clear to me. Care to define and clearly explain such a set of rules? >It seems somewhat inconsistent to me. Is there some way to dynamically bind >to the overloaded g() based on its argument type? Your request can be broken down into two parts. The first could be considered: "Is there some way to use C-function syntax instead of member-function syntax?" The answer to this part is trivially answered yes: inline C_g(SOMECLASS& ob) { ob.member_g(); } Now that we've gotten the syntax issue out of the way, the question becomes: "Is there some way to add a member function "g" to an existing set of classes?" The answer to this part of the question is yes too, if ugly: extern "C" void printf(const char*, ...); class B { public: virtual void f(); }; void B::f() { printf("B::f()\n"); } class D : public B { public: virtual void f(); }; void D::f() { printf("D::f()\n"); } /***** pretend the above classes are immutable *****/ /***** then your g(ob) functionality can be met as follows *****/ class G { public: virtual void g(); }; /*** below should be pure virtual, depending on your compiler ****/ void G::g() { printf("G::g() shouldn't be called at all! "); } class BG : public G, public B { public: virtual void g(); }; void BG::g() { printf("B::g() can use members like "); f(); }; class DG : public G, public D { public: virtual void g(); // normally, the below would be unfair, but in this case, a DG *is* // both a B and a G, and therefore a BG. operator BG&(); }; DG::operator BG&() { return *((BG*)((G*)(this))); } void DG::g() { printf("D::g() can use members like "); f(); } void g(BG& b) { b.g(); } void g(DG& d) { d.g(); } #define B BG #define D DG /**** now let's try the new "enhanced" versions of B and D ****/ main() { B b; D d; g(b); g(d); B& br = d; D& dr = d; g(br); g(dr); } ----------- Obviously, this approach works just as well if ::g(DG&) and ::g(BG&) are members of some class, rather than globals. [I am not recommending this approach, mearly pointing out that it can be done.]