home *** CD-ROM | disk | FTP | other *** search
- Newsgroups: comp.lang.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: Downcasting (was: Re: run-time type checking)
- Message-ID: <1992Aug21.004033.15204@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: <1992Aug15.170141.14667@ucc.su.OZ.AU> <4847@holden.lulea.trab.se>
- Date: Fri, 21 Aug 1992 00:40:33 GMT
- Lines: 165
-
- In article <4847@holden.lulea.trab.se> jbn@lulea.trab.se (Johan Bengtsson) writes:
- >: In a statically secure system, I argue that it is important to access
- >: an object only by its explicitly declared accessible interface.
- >
- >**** I think _that_ is the issue. I'd say a system can be statically
- > secure, even if it does (undeclared) runtime-checked down-casts
- > (that is, if the program only does the down-casts when possible).
-
- You may be right, I certainly dont have a more convincing argument
- than the example I gave before:
-
- class X {
- protected:
- int i;
- public:
- int get()const {return i;}
- X(int j) : i(j) {}
- };
-
- class Y : public virtual X {
- public:
- Y(int j) : X(j) {}
- void set(int j) { i=j;}
- };
-
- f(X&);
- Y aY;
- f(Y);
-
- I am disturbed by the fact that f can modify its X object when the
- interface says it cant.
-
- > I think we agree on the need to sometimes do controlled downcasts.
-
- Dont know what you mean by 'sometimes'. I propose no
- downcasting, ever. Ban even existing legal downcasts. I know this
- is overly restrictive, but any loosening of the restriction I would
- accept without further involved argument cannot do what the
- downcasting advocates want---to downcast to a class without
- explicit interface modification is necessary for extensibility.
-
- The issue then is whether there is a price to pay for the
- extensibility or not. I argue there is, although I could be wrong.
- To convince me you have to assert that nothing valuable is lost
- in the case given above. In that case, the assumption I could make
- that Y.i remains constant over the call to f is violated if
- downcasting is allowed. At least there is a lost optimisation
- opportunity. At worst all of polymorphism is destroyed.
- >
- > I also admit that when you see a need for a downcast, you should
- > ask yourself why you have lost track of the type of the object,
- > and change the code to avoid it, if possible. Downcasting is a
- > last resort. Yes, I use GOTOs too (in the form of break/continue
- > statements).
-
- Downcasting is an ABUSE of the concept of polymorphism,
- it tries to mix up the ideas of polymorphism with heterogeneity.
- These are totally different mechanisms conceptually that unfortunately
- both can be implemented using inheritance.
-
- >
- > You may argue that the system is easier to _maintain_ by making the
- > possible down-casts visible in the base class, and I would agree.
-
- No, I argue that to mix polymorphism and heteromorphism
- in inheritance, you need to distinguish which 'bits' are poly
- morphic and which are hetero-morphic.
-
- I see the problem is that because you can add arbitrary
- derived classes polymorphically people assume they can arbitrary
- classes heterogeneically too. This is false IMHO. Heteromorphic
- extensions are always finite and non-arbitrary (there is a specific
- number of them, and you need to handle all the cases separately,
- i.e., you need a compile time 'switch'.) But polymorphism
- handles infinite (arbitrary) cases by using indirection,
- i.e. vectoring. Here the address is not known, but the address
- of the address is. The actual function is not known, but
- the addresses of all the functions ARE known.
-
- A switch does not and cannot have this property.
- The fact that downcasting requires
-
- a) Run-time type info
- b) Compile time explicit case codes to be written
-
- the most dynmaic and most static of concepts togther, seems to say
- something is inappropriate. Mm.
-
- Lets have a look at this:
-
- void (*f)(X&); // function pointer
- ...
- f(x); // vectored call
-
- This is statically typesafe and works for ARBITRARY functions
- that might be assigned to f. The price one pays for the ARBITRARYness
- is that ALL the functions you can assign to f MUST have the same
- interface.
-
- Now:
-
- switch (...)
- case ..: f(1);
- case ..: f('m',2.1);
- ...
-
- Here there is a fixed list of cases, and the f's are unrelated
- except by name. They are quite specific f's, and take different
- parameters. Also type safe.
-
- Now the downcasters want to do BOTH the above simultaneously,
- to have type safe arbitrary switching/vectoring, and I dont
- believe its possible.
-
- >
- >: >
- >: > The importance is that in neither case do you have to
- >: > intervene with the source or compiled code of the base
- >: > class to do what you want. This is considered good
- >: > for behaviour (overriding virtuals), so why not also
- >: > for interfaces (unrestricted but safe downcasting)?
- >:
- >: It is sound for virtuals because they are declared!
- >
- >**** But not in the base class! You can't find out which
- > derived classes override a virtual by inspecting the
- > base class.
-
- Of course not. You dont CARE how or whether the derived class
- defines the virtual. Indeed you MUSTNT KNOW. And you dont NEED to know.
- That lack of knowledge is power. Only by denying all knowledge
- can you claim arbitrariness, and only with arbitrariness do you
- have openness.
- >
- >: > A base class intended for future inheritance (even by
- >: > other programmers) should support overriding behaviour
- >: > using virtual member functions, and should support
- >: > interface extension by runtime-checked, safe downcasting.
- >: >
- >: > This lessens the risk that future users without access to the
- >: > source code will get stuck when deriving from the base class.
- >:
- >: The point of polymorphism is that
- >: your should not rely on derived class behaviour in routines
- >: given a base object, and you shouldn't need to.
- >
- >**** But you do, since any derived class may have an
- > incorrect implementation of a virtual method.
- >
- Yes, but that is another issue. In principle
- there are invariants etc, and you shouldnt violate them
- even if the language can't check them.
-
- You MUST rely on the implementor of a derived class
- not violating the semantics of the base class, because there is
- no other option. You cant check the semantics of an arbitrary
- and not yet written derived class in the base class completely,
- although invariants might help narrow the illegal
- cases down.
-
- --
- ;----------------------------------------------------------------------
- JOHN (MAX) SKALLER, maxtal@extro.ucc.su.oz.au
- Maxtal Pty Ltd, 6 MacKay St ASHFIELD, NSW 2131, AUSTRALIA
- ;--------------- SCIENTIFIC AND ENGINEERING SOFTWARE ------------------
-