Path: utzoo!attcan!utgpu!jarvis.csri.toronto.edu!cs.utexas.edu!samsung!zaphod.mps.ohio-state.edu!tut.cis.ohio-state.edu!att!dptg!pegasus!psrc From: psrc@pegasus.ATT.COM (Paul S. R. Chisholm) Newsgroups: comp.lang.c++ Subject: class "names" at runtime (was Re: Design Problem) Summary: "name" just has to be unique, not really a string Message-ID: <4329@pegasus.ATT.COM> Date: 14 Dec 89 17:49:13 GMT References: <22137@brunix.UUCP> <3164@cbnewsl.ATT.COM> Organization: AT&T Bell Laboratories Lines: 87 From article <22137@brunix.UUCP>, by sdm@cs.brown.edu (Scott Meyers): > 2. Add an enumerated type to ARC that enumerates each of the > subtypes, and add a virtual function arc_type() that is redefined in > each subclass to return the appropriate value. Then I can write > code like "if (arc->arc_type() == EXECUTABLE) arc->evaluate()". In article <3164@cbnewsl.ATT.COM>, dog@cbnewsl.ATT.COM (edward.n.schiebel) writes: > I found a need to do this once (or twice :-), but (as you mention later) > it suffers from having to modify the base class when you derive a > new type from it. I have a variation on this theme which does not > suffer from this weakness: > class base { > public: > virtual String type(); > }; Well, it's nice that the "class name" is printable, but it doesn't need to be as flexible as a String. In Smalltalk-80 (TM), there's a subclass of String known as Symbol. Symbols are implemented as Strings, but are kept in a table so they're guaranteed unique. Thus, to compare two Symbols, all you have to do is compare the character pointers (in C++; in Smalltalk-80, the "=" operator is the same as the "==" operator, and you just see if two Symbols are identically the same object, I think). So let's say (I haven't run any of these through the compiler): class base { private: static char *Typename; // initialized to "base" somewhere ... public: // type() -- return a pointer to a constant name virtual const char* type() { return Typename; // that is, base::Typename }; static const char* Stype() { return base::Typename; }; ... }; > class derived : public base { > pubic: > static String Stype() {return type_string;} > String type() {return Stype();} > private: > static String type_string; // initialized to "derived" in .c file > }; class derived : public base { private: static char Typename[]; // initialized to "derived" somewhere ... public: const char* type() { return Typename; // that is, derived::Typename }; static const char* Stype() { return derived::Typename; }; }; > Now the test becomes: > if(base_ptr->type() == derived::Stype()) doSomething() > (assuming class String has operator== defined of course). > This test (a String comparison) is not that much more expensive than > an integer test, since in many cases, the comparison will fail in the > first character (unless your clas hierarchy looks like arc_generic, > arc_this, arc_that, arc_theotherthing). The test base_ptr->type() == derived::Stype is just a comparison of two pointers. Can't put them in case statements, though. And you'd better get them right (re-implement it in every class)! Turbo Pascal 5.5 has an interesting approach: the "type name" is the pointer to the "virtual method table", and every object of a virtual class responds to the message "TypeOf". > Ed Schiebel, AT&T Bell Laboratories, dog@vilya.att.com Paul S. R. Chisholm, AT&T Bell Laboratories att!pegasus!psrc, psrc@pegasus.att.com, AT&T Mail !psrchisholm I'm not speaking for the company, I'm just speaking my mind. Smalltalk-80 is a trademark of Parc Place Systems, or Xerox, or somebody.