home *** CD-ROM | disk | FTP | other *** search
- Xref: sparky comp.lang.c++:11411 comp.std.c++:925
- Newsgroups: comp.lang.c++,comp.std.c++
- Path: sparky!uunet!munnari.oz.au!metro!extro.ucc.su.OZ.AU!maxtal
- From: maxtal@extro.ucc.su.OZ.AU (John MAX Skaller)
- Subject: Re: run-time type checking (was: Re: Covariant Types in Derived Classes)
- Message-ID: <1992Jul23.154254.5306@ucc.su.OZ.AU>
- Sender: news@ucc.su.OZ.AU
- Nntp-Posting-Host: extro.ucc.su.oz.au
- Organization: MAXTAL P/L C/- University Computing Centre, Sydney
- References: <1992Jul21.162659.25474@ucc.su.OZ.AU> <1992Jul22.022218.1115@cadsun.corp.mot.com>
- Date: Thu, 23 Jul 1992 15:42:54 GMT
- Lines: 332
-
- In article <1992Jul22.022218.1115@cadsun.corp.mot.com> shang@corp.mot.com writes:
- >In article <1992Jul21.162659.25474@ucc.su.OZ.AU> maxtal@extro.ucc.su.OZ.AU
- >(John MAX Skaller) writes:
- >> In general C++ programming I do not agree that it is
- >> necessary to recover arbitrary type information. That is because,
- >> quite simply, you CANNOT use it.
- >>
- >"In general C programming I do not agree that it is necessary to use
- >inheritance of structure. That is because, quite simply, you CANNOT use it"
-
- Sorry, I'm not sure what you mean be inheritance of structure.
-
- > I don't like the argument. We are not talking about C++ programming. We are
- >talking about the enhancement of the C++. If this argument could make any
- >sense, why should we need C++?
-
- Well, we need C++ because it can do lots of nice things already.
-
- >
- >> I think I should clarify here: I am arguing against
- >> DOWNCASTING.
- >>
- >I am against *unsafe* downcasting too. What we are arguring about is not the
- >downcasting.
-
- Ah: you misunderstand! I REALLY ARGUE AGAINST DOWNCASTING.
-
- >It is the run time type checking: whether it is necessary.
-
- Given the need to do downcasting, to do it safely run-time
- type information is required. But I am arguing it is not necessary
- to downcast. So the question of needing run-time type info to
- do it doesn't arise.
-
- >
- >> I am not against collections of objects all derived
- >> from a common base provided you access them via the base.
- >> That is the vey point of inheritance, after all.
- >> In this case the objects are all of the same type:
- >> it is homogeneous at the level it is accessed and
- >> heterogeneous at the actual object level, but the actual
- >> object level is not accessible.
- >>
- >True. I'm always in favor of doing that. We can always add member funtions and
- >virtual member functions to aviod downcasting an element in a *domestic*
- >heterogeneous collection or structure.
-
- Ah. I like your word *domestic*. But your statement shows backwards
- thoughts: we do not add virtual functions to "avoid downcasting".
- We design our systems properly in the first place, and then the need
- to downcast never arises, when our thoughts wander in that
- direction one can be sure we are not thinking virtuously,
- and perhaps the design itself is flawed.
-
- Inother words, in a *domestic* system, any apparent
- need for downcasting should be used as an indicator of flawed design.
-
- >But this does not mean that the run time
- >type info is not necessary. In case of a foreign heterogeneous collection, we
- >often need the run time type info, need to store and export the type info
- >together with the object.
-
- Ah, now *foreign* systems. Here, in general, we cannot
- store objects directly, they must be encoded somehow. That encoding
- is the run-time type info.
-
- The problem is that you don't HAVE th objects to get the run
- time info FROM. You have the encodings, and the object type info
- is in the encoding --- not the object. So of course you must
- extract it to create an object of the appropriate type--- and to
- do that implies you KNOW the run-time type BEFORE you create
- the object, so it follows you dont need to ask the object
- for its type---you already knew the type when you created it.
-
- The exception---the time you DO need run-time type info
- is when you have a *meta-domestic* system. Like a debugger,
- it is a system designed to manage systems, and BOTH happen
- to be already C++. THEN you could use RTTI.
- >
- >> I am not against collections of objects of completely
- >> unrelated types provided the types are drawn from a finite
- >> and statically known set. In this case there is a 'type' which
- >> is the finite union of those types, so again, the collection
- >> is really homogeneous wrt that type.
- >>
- >This case exactly examplifies the necessity of runtime type info. Given an
- >element in this collection, you need run time type info to identify its type.
- >Otherwise, how do you do with the element which may be in one of the types that
- >are *completely unrelated*, say { int, float, doulbe }?
-
- You need to know the type. But you DO NOT HAVE TO ASK THE OBJECT
- WHAT TYPE IT IS. You have to store a code WITH the object that you
- access separately.
-
- And notice there is NO issue of downcasting here. The issue
- is one of SELECTION. From a FINITE number of alternatives.
- From a KNOWN FINITE number of alternatives.
-
- In the case of downcasting from a base to a derived class
- you CANNOT know the alternatives, you CANNOT know what the
- derived types are,m because THAT LACK OF KNOWLEDGE IS
- FUNDAMENTAL to the idea of inheritance.
- >
- >>
- >> I am against using, in general programming,
- >> DOWNCASTING or run-time type information to defeat the type system.
- >>
- >I just don't understand!
- >Run time type check is a facillity to prevent careless
- >downcast to defeat the type system.
- >How can you say that it is used in general
- >programming to defeat the type system?
-
- Because if you are using it in *domestic* programs to downcast
- safely, you are using it to downcast, and downcasting is defeating
- a promise made by the concept of inheritance: that promise is
- called the OPEN/CLOSED principle. It is the cornerstone of
- object oriented design (well, actually, class-oriented design).
-
- It makes the promise that an algorithm applied to
- a class B will continue to work for ALL classes D1, D2, D3
- where D1, D2, etc are derived fomr B.
-
- The way this promise is enforced is to hide ALL
- details of D1, D2, D3 etc other than those shared in
- class B from the algorithm.
-
- If you downcast from the base class B you are learning
- something about, say, class D1 that you weren't supposed to know.
- If you use that knowledge, you will become unstuck.
-
- Let me give you an example. Suppose class D1 has a function
- f() while B has no such function. You have an algorithm that
- downcasts to D1 from B and calls f().
-
- But then you change D1 to NOT have a function f().
-
- Suddenly, the algorithm FAILS. (It won't even compile).
- [Too bad if the algorithm was locked away in binary form,
- then it will fail at link time, or if linkage is dynamic, who knows?]
-
- Now you see you have caused an algorithm which, by its
- declaration ONLY DEPENDED ON THE INTERFACE (and semantics :-)
- of class B to fail --- BY MODIFYING D1, which is derived from
- B. You have VOIDED THE OPEN/CLOSED PRINCIPLE by using a downcast.
-
- Now again: before we can discuss when and how to use RTTI, I need
- you to understand that the OPEN/CLOSED principle is voided
- by using downcasting and to agree that this is not desirable.
-
- I need you to see the issue IS NOT ABOUT THE SAFETY OF DOWNCASTING.
-
- The issue is, how can one carefully discriminate the legitimate
- use of RTTI in *meta-domestic* systems, and maybe in
- *foreign* systems, from its illegitimate use for
- downcasting in *domestic* systems.
-
- >
- >> I agree that in Debuggers and other such programs
- >> these facilities are essential, indeed, you need much more
- >> than a mere safe downcast or run-time type code. In a debugger,
- >> for example, you need in effect run-time access
- >> to the complete declaration and definintion of each class in
- >> the whole program!
- >>
- >A simple type id can be a key for a debugger to access to the complete
- >declaration and definintion of each class in the whole program. We are not
- >necessary to include the complete type information at run time.
-
- You do if the debugger is any good.
- >
- >> C++ does NOT have facilities at present to do this.
- >> I am NOT against adding them. But I would be against using these
- >> facilities in the general programming context for which C++
- >> was intended and where such mechanism are *dangerous*.
- >>
- >Again, I can't understand.
- >Run time type check is not a dangerous mechanism.
-
- Run time type information is INHERENTLY DANGEROUS,
- because it can provide access to information that the type
- system has DELIBERATELY HIDDEN. The only reason you want run-time
- information is that YOU DONT HAVE INFORMATION THE SYSTEM HAS
- HIDDEN FROM YOU DELIBERATELY, PREICSELY BECAUSE ANY ATTEMPT
- TO USE THAT INFORMATION IS UNSAFE TO USE.
-
- The fact that you can use it to convert a base class
- does not make that conversion safe. Just because you get back
- a pointer you know is the right type DOESN'T mean
- you were entitled to use that pointer.
-
- >On
- >the contrary, it is used prevent potential dangers.
- >
- >> Clearly, for example, a debugger which allows you
- >> to modify instances of a class breaks encapsulation!
- >> It breaks almost every principle you can think of.
- >> It is meant to: you use the debugger when a more important
- >> thing is already broken : your program :-)
- >>
- >Here, you goes too far. A debugger can break every principle of encapsulation
- >and protection only through low level programming facillities (e.g. the bitwise
- >and bytewise read/write, enforced typecasting between different types, machine
- >addresses, etc.).
-
- You confuse 'breaking the system' with causing a fault.
- To cause a fault, you need only write somewhere in memory
- that you weren't meant to. To do that you MUST use a cast.
- So casts are bad. (Conversions are not, however).
-
- A 'hacker' breaks system security when e accesses the system.
- That doesn't mean the system is 'messed up', or the file system
- destroyed. None-the-less, the system is *broken* when security
- is breached *even if no damage is done*.
-
- In the case of downcasting the problem is the same as for
- any old casting: you have access to information you shouldn't have.
- The reason you shouldn't have it is that if you do you MIGHT
- proceed to destroy the system integrity, by breaching
- promises the system has made.
-
- For example, if I give you an animal pointer,
- and it has read only functions ONLY, I expect the object to
- remain unchanged.
-
- If you cast it to a Mammal, which has mutator functions,
- and proceed to mutate it, I will be very annoyed. I want the
- system to PROMISE ME YOU CANT DO THAT, at least not privately.
-
- >But a debugger can never break any principle of encapsulation
- >and protection only through run time type check.
-
- OF COURSE IT CAN. The debugger has access to the
- private data of an object. The debugger is not a member function
- of the object. THEREFORE, unequivocably, the debugger has broken
- the encapsulation of the object (even if it is a benign debugger
- and wont abuse the priviledge).
-
- >Remember: run time type checking does not allow to cast objects
- >which are actually of different types.
-
- Agreed. But it facilitates casting. Casting is bad.
- (Usually) Since we dont want to cast things, we dont need to
- do it safely!
-
- >
- >Even we stick to homogeneous programming, we still need run time type checking.
- >One of your reason against the concept of "thisclass" is that it needs run time
- >type checking, which you view as a disadvantadge. "thisclass" is just a
- >facillity to describle homogeneous data structure.
-
- Yes. I'm not necessarily against 'thisclass', I merely pointed out
- that it has some disadvantages. Requiring RTTI is a disadvantage
- because we dont yet have it :-)
- >
- >Okay, let's get rid of the concept of "thisclass" for the time being. Now, is
- >it true that run time type checking is no longer needed for homogeneous data
- >structure? No.
-
- We still disagree: for domestic systems, yes, RTTI is NEVER
- needed. I've never needed it. I always know what types I'm working with!
-
- [Actually, i cheat a bit in template classes to achieve code reuse,
- I sometimes cast void* to T*, but is not NECESSARY, just expedient]
-
-
- >Without covariant type specification (now, we come to our
- >original subject) in derived classes, we still have to run time type check the
- >type of arguments in derived classes in order to prevent any violation.
-
- NO, you have to accept the restriction of single dispatch.
- The ONLY object you know the type of is the *this object.
- (And any others passed by value).
-
- >Let's
- >consider a homogeneous animal collection:
- >
- > class Animal;
- > class AnimalGroup
- > { protected:
- > Animal * animals;
- > public:
- > virtual void accept (Animal *ap) {...};
- > ...
- > };
- >
- >Since it is a homogeneous collection, it should contains animals of the same
- >type. The concept of "same type" is relatively dependend on what the class
- >designer means.
-
- No, quite wrong. Same type means 'common properties
- of all animals'. It SPECIFICALLY excludes you knowing about
- whether the animal has webbed feet. Because snakes dont have
- feet, so its not a property common to all animals.
-
- >Suppose the same type" is based on the *family* according to
- >the systemtic zoology. Then the collection should be of all dogs, or all cats,
- >etc.
-
- Then you should have a collection of all dogs, or all cats,
- not all animals.
- This is why some people like templates a lot.
-
-
- Now you have further example of a serious problem, but I will
- simplify it.
-
- The problem is why you proposed 'thisclass' and is a real problem.
- It is a problem for which RTTI is the wrong solution,
- but never-the-less is the best we will get for a while.
- We really need multiple dispatch.
-
-
- class Animal {
- int mate(Animal&);
- };
- class Dog : Animal {
- int mate (Animal&);
- };
-
- We REALLY want Dog::mate(Dog&), but we cant have it.
-
- This is a flaw in Object Oriented Programming IMHO.
- The solution requires multimethods which are inherently
- functional.
-
-
- --
- ;----------------------------------------------------------------------
- JOHN (MAX) SKALLER, maxtal@extro.ucc.su.oz.au
- Maxtal Pty Ltd, 6 MacKay St ASHFIELD, NSW 2131, AUSTRALIA
- ;--------------- SCIENTIFIC AND ENGINEERING SOFTWARE ------------------
-