home bbs files messages ]

Forums before death by AOL, social media and spammers... "We can't have nice things"

   comp.lang.c++.moderated      Moderated discussion of C++ superhackery      33,346 messages   

[   << oldest   |   < older   |   list   |   newer >   |   newest >>   ]

   Message 31,690 of 33,346   
   Ulrich Eckhardt to All   
   Re: Covariant virtual function result ty   
   24 Nov 11 12:39:30   
   
   8807a3ed   
   From: ulrich.eckhardt@dominolaser.com   
      
   Am 24.11.2011 01:40, schrieb Lorenzo Caminiti:   
   > When invoking a covariant virtual function, the derived function body   
   > is executed but the result type of the base function is returned. Is   
   > there any way to get C++ to return the result type of the derived   
   > function instead?   
      
   Generally, there are static types and dynamic types. The static type is   
   what the compiler verifies and where it issues errors on mismatches. The   
   dynamic type is used at runtime, when using RTTI or doing virtual   
   function calls.   
      
   The type of something returned by a function is static, meaning that it   
   can't change at runtime. The dynamic type can change, if you have a   
   pointer to "Base", the dynamic type may well be "Derived".   
      
      
   > struct rx {};   
   > struct ry : rx {};   
   >   
   > struct x {   
   >     virtual rx* f() {   
   >         std::cout<<  "rx* f()"<<  std::endl;   
   >         return&rx_;   
   >     }   
   >     rx rx_;   
   > };   
   >   
   > struct y : x {   
   >     ry* f() {   
   >         std::cout<<  "ry* f()"<<  std::endl;   
   >         return&ry_;   
   >     }   
   >     ry ry_;   
   > };   
      
   Virtual function returning a pointer, derived class returning a pointer   
   to another derived type, i.e. covariant return type. Nothing special here.   
      
      
   > int main ( ) {   
   >     y yy;   
   >     y* yp =&yy;   
   >     x* xp =&yy;   
   >   
   >     ry* ryp = yp->f(); // calls y::f   
   >     rx* rxp = xp->f(); // calls y::f but returns rx* instead of ry*   
      
   The static type of "xp->f()" is "rx*", this can't change at runtime.   
      
   > //    ry* nope = xp->f();   
   > // error: calls y::f but returns rx* instead of ry*   
      
   Okay, there are a few ways out:   
   1. You know that "xp" points to an "y", so you also know that the   
   returned "rx*" is actually an "ry*". What you can do is to simply use a   
   "static_cast()" to convert the result. Of course, if you make a   
   mistake and "xp" does not point to an "y", you are invoking undefined   
   behaviour. If "rx" was polymorphic, i.e. at least one virtual function,   
   you could use a dynamic_cast.   
      
   2. Since you know that "xp" points to an "y", just convert that to an   
   "y*" using "static_cast(xp)". If you use that to invoke a function   
   "f()", it will statically find "y::f" which has the expected return   
   type. Note that here you can also use a "dynamic_cast" in order to   
   verify the type.   
      
   3. You could replace the type "rx" in the baseclass' with "ry".   
      
   4. Using templates, you could then avoid writing similar code for "x"   
   and "y", instead just pass them in as template parameters.   
      
   5. You could create a visitor (look up "Visitor Pattern") that does the   
   right thing for different types. This would just allow you to cleanly   
   call the according different code and is an alternative to using dynamic   
   casts in order to find the correct type.   
      
   In most cases, the question you will have to answer is whether you know   
   the type or not. If you know it, a static cast with possible a comment   
   explaining it should do the job. If you don't know the type, you must be   
   able to gracefully handle both "x" and "y", and for that some kind of   
   dynamic dispatch is needed, either via virtual functions or dynamic cast.   
      
   Good luck!   
      
   Uli   
      
      
   --   
         [ See http://www.gotw.ca/resources/clcm.htm for info about ]   
         [ comp.lang.c++.moderated.    First time posters: Do this! ]   
      
   --- SoupGate-Win32 v1.05   
    * Origin: you cannot sedate... all the things you hate (1:229/2)   

[   << oldest   |   < older   |   list   |   newer >   |   newest >>   ]


(c) 1994,  bbs@darkrealms.ca