Path: utzoo!attcan!utgpu!news-server.csri.toronto.edu!mailrus!iuvax!rutgers!uwvax!tank!ux1.cso.uiuc.edu!ux1.cso.uiuc.edu!uxa.cso.uiuc.edu!wevg0324 From: wevg0324@uxa.cso.uiuc.edu Newsgroups: comp.lang.c++ Subject: Re: Getting Type Information at Runtime Message-ID: <47700002@uxa.cso.uiuc.edu> Date: 26 May 90 14:01:00 GMT References: <40876@brunix.UUCP> Lines: 68 Nf-ID: #R:brunix.UUCP:40876:uxa.cso.uiuc.edu:47700002:000:3089 Nf-From: uxa.cso.uiuc.edu!wevg0324 May 26 09:01:00 1990 First let me say that I DO recognize that sometimes it is very useful to determine an object's class at runtime, expecially in debug printf's. HOWEVER: > What I want to come up with is a simple way to do things like > switch (object->type()) { > case class1: dosomething1(); break; > case class2: dosomething2(); break; > case class3: dosomething3(); break; > } You almost certainly do NOT want to use a switch statement here. Instead use virtual methods (they are both faster, and "more object oriented"). Replace that switch statement with: virtual class1::switch_dosomething() { dosomething1(); }; virtual class2::switch_dosomething() { dosomething2(); }; virtual class3::switch_dosomething() { dosomething3(); }; and the call: object->switch_dosomething(); =============================================================================== > Finally, I'd like the approach to be extendable so that I can test "isa" > relationships. That is, I can say things like > if (isa(object1, object2)) ... > and the condition will evaluate to true iff object1 and object2 are of the > same class or there is a public inheritance path from object2 to object1. This is a seperate problem. First create a root super class for all the objects you wish to compare with isa relations. Then for each subclass $name, add the following method to the "root" class, expanding "$name" as appropriate: virtual kindOf$name() { return(false); }; Then in each class "$ThisClass" including "root" add the methods: virtual kindOf$ThisClass() { return(true); }; virtual isa(root *object2) { return(object2->kindOf$ThisClass()); }; NOTE: The call object->kindOf$name() answers the question, NOTE: is it legal to assign the "object" pointer to a NOTE: variable of type "$name *ptr" without a cast. Now rewrite your "if (isa(object1, object2)) ..." statement as "if (object1->isa(object2)) ..." > It should also be possible to test this relationship using class > identifiers, e.g., something like > if (isa(object1, placeHolderForClassX)) ... > if (isa(placeHolderForClassX, object1)) ... Just use the "kindOf$name()" methods directly. =============================================================================== A closely related trick you may find useful is the method "asA$name()." The purpose of this method is to allow you to do the following in a typesafe manner (no casts): root_class *root; child_class *child1, *child2; ... root = child1; // Always legal in C++ ... child2 = root; // Normally a cast is needed on this line // but a cast tells the compiler "trust me." In the root class, for each subclass $name add the method: virtual *$name asA$name() { return(0); }; // Or perhaps assert(0). Then in each class add the method: virtual *$name asA$name() { return(this); }; =============================================================================== billvoss@uiuc.edu or voss@cs.uiuc.edu or voss@a.cs.uiuc.edu Bill Voss -- Graduate Student, Department of Computer Science University of Illinois in Urbana/Champaign