Relay-Version: version B 2.10 5/3/83; site utzoo.UUCP Path: utzoo!mnetor!seismo!elsie!nih-csl!keith From: keith@nih-csl.UUCP (keith gorlen) Newsgroups: comp.lang.c++ Subject: Re: Questions about C++ (Rather Long) Message-ID: <227@nih-csl.UUCP> Date: Wed, 24-Jun-87 09:44:58 EDT Article-I.D.: nih-csl.227 Posted: Wed Jun 24 09:44:58 1987 Date-Received: Sat, 27-Jun-87 00:52:52 EDT References: <226@nih-csl.UUCP> <131@otc.OZ> Distribution: comp Organization: NIH-CSL, Bethesda, MD Lines: 61 Summary: Suggested technique for testing the class of an object has some problems. In article <131@otc.OZ>, mikem@otc.OZ (Mike Mowbray) writes: > // *********************** typetst.c ************************************* > #include > > #define IS_TYPE(classtype,instance) ((instance)._vptr == ::classtype\ > __vtbl) > // "classtype" must have virtual functions. > // "instance" must be an instance of a class with virtual > // functions (or a reference thereto). > // If either is not the case, there'll be a compile-time error. > // (either "_vptr: no such member" > // or "xxxxx__vtbl is undefined" > // or something like that.) > //-------------------------------------------------------- This technique assumes that all instances of a class will have the same vtbl address, which is not true unless you use the +e compiler switch. Without this switch, each .c file that #includes the declarations of a class with virtual functions gets its own instance of vtbl, and objects constructed by code in two different .c files will have different vtbl addresses as a result, even though they may belong to the same class. Since using the +e switch is such a pain, I wouldn't recommend this method. > > Note also, that IS_TYPE doesn't work for derived cases: > > Association assoc; > > if (IS_TYPE(Object,assoc)) // will yield 0. > ..... > > To remedy this is harder since extra type information is needed. E.g: you > could have a table associated with each class which keeps track of all > its ancestors' vptrs. Each instance would need a pointer to the correct > table. The following is an example: > My OOPS class library uses instances of class Class to describe the class hierarchy at run-time. The programmer must declare one, static, instance of class Class for each class he writes. Each instance of class Class contains a pointer to the instance of class Class that describes the base class, the class name as a character string, the size in bytes of instances of the class described, the address of a function for reading instances of the class from a stream, and other useful information. Each class defines the virtual function const Class* isA() to return the address of its Class descriptor instance. Also, the (static) constructor for class Class adds all the Class instances linked in the program into a Dictionary, keyed by the name of the class. This structure supports run-time type checking, object I/O, object copying operations, object I/O (i.e., storeOn(ostream&) and readFrom(istream&)), and allows class names to be printed in error messages. It has low overhead, and adds no additional member variables to objects. I've been using it for over a year, and am satisfied with it, except that I wish I had named the class something else! (The whole idea was stolen from Smalltalk-80) -- Keith Gorlen phone: (301) 496-5363 Building 12A, Room 2017 uucp: seismo!elsie!nih-csl!keith National Institutes of Health Bethesda, MD 20892