Path: utzoo!utgpu!news-server.csri.toronto.edu!cs.utexas.edu!usc!julius.cs.uiuc.edu!rpi!bu.edu!att!cbnewsl!cbnewsk!ech From: ech@cbnewsk.att.com (ned.horvath) Newsgroups: comp.sys.mac.programmer Subject: Re: Casting in Think C Message-ID: <1990Dec6.203755.9266@cbnewsk.att.com> Date: 6 Dec 90 20:37:55 GMT References: <6194@munnari.oz.au> Organization: AT&T Bell Laboratories Lines: 62 In article <6167@munnari.oz.au>, caw@munnari.oz.au (Chris Wright) writes: > Why do you have to cast gApplication in ThinkC e.g.: > extern CApplication *gApplication; In article <3028@skye.cs.ed.ac.uk>, nick@cs.edinburgh.ac.uk (Nick Rothwell) writes: > gApplication is still a CApplication, and hence doesn't have an IEditApp() > method unless you cast it. From article <6194@munnari.oz.au>, by caw@munnari.oz.au (Chris Wright): > > If my memory serves me correctly, gApplication is now a > CEditApp. This can be checked with the member function. > So it SHOULD have an IEditApp(). And the compiler > shouldn't complain. > Though see the kind reply from Symantec earlier in this > thread (which I'm not sure if I understand!) In Think's (Object) C, as well as in C++, the members (data fields or messages) you can refer to depend upon the "static," or declared, type of the object reference. Notice I said "can refer to," i.e. the compiler will complain: it must generate code based upon what every CApplication -- not just CEditApp -- can do. In this case, gApplication is a reference to a CApplication, so the available members are those of a CApplication. If you "know" it's a reference to a specific subclass, you can still get at the subclass's special messages by casting: if (member (gApplication, CEditApp)) { ((CEditApp*)gApplication)->IEditApp(...); } else { gApplication->IApplication(...); } The rules aren't arbitrary: YOU can see the "new (CEditApp)", but the compiler only depends on the declaration. As an aside, this isn't the only way to do things. SmallTalk allows any message to be sent to any object, with a default method of "that object doesn't know how to do that." The philosophy is that you don't want to implement a method until you need it. The C++ (and Object C) philosophy is that you should plan ahead. I won't defend the rules further, except to state my opinion that C++ has the right rules for production software: my customer doesn't know what to do with "*gApplication doesn't know how to IEditApp." Notice that in practice, you almost never need to actually write the casts. Initialization is the most common case, in fact, and if you want clean, no cast code, try: CMyAppType *myApp; ... myApp->IMyAppType(...); ... gApplication = myApp; /* clean if CMyAppType inherits from * CApplication. */ Hope that helps... =Ned Horvath=