RE:Base class method

From: Masaharu Goto (MXJ02154@nifty.ne.jp)
Date: Tue Nov 23 1999 - 00:44:23 MET


Dear Victor,

Thank you for reporting this problem. I found out the cause. The
problem occurs when you call a virtual function of a precompiled class
with scope operator. Unfortunately, this one will be left as it is. 
Here is the reason.

This is deeply related to dictionary operation. Cint is calling 
wrapper function for TObject::GetName, but because it is a virtual 
function, it ends up calling TNamed::GetName. I will explain in a simple
source.

  // user header ////////////////////////////////////////////
  class A {
   public:
    virtual const char* GetName() const { return("base"); }
  };
  class B : public A {
   public:
    const char* GetName() const { return("derived"); }
  };

If you do makecint or rootcint on this header, dictionary would look like
below.

  // dictionary /////////////////////////////////////////////
  static int G__A_GetName_0_0( .... ) {
     ...
    const char* result = ((A*)obj)->GetName(); // virtual function call
     ...
  }

  static int G__B_GetName_0_0( .... ) {
     ....
    const char *result = ((B*)obj)->GetName(); // virtual function call
     ....
  }

Cint calls  G__B_GetName_0_0 for tn->GetName() and G__A_GetName_0_0
for tn->TObject::GetName(). However, because A::GetName is a 
virtual function, it resolves to B::GetName(). As cint distinguishes
two cases correctly, it is technically possible to solve this problem.
Problem is that we have to almost doulbe the dictionary size.
Every virtual function, we have to have virtual and non-virtual wrappers.

  // dictionary /////////////////////////////////////////////
  static int G__A_GetName_0_0( .... ) {
     ...
    const char* result = ((A*)obj)->GetName(); // virtual function call
     ...
  }
  static int G__B_GetName_0_0( .... ) {
     ....
    const char *result = ((B*)obj)->GetName(); // virtual function call
     ....
  }
  static int G__A_GetName_0_0_nonvirtual( .... ) {
     ...
    const char* result = ((A*)obj)->A::GetName(); // non virtual
     ...
  }

  static int G__B_GetName_0_0_nonvirtual( .... ) {
     ....
    const char *result = ((B*)obj)->B::GetName(); // non virtual
     ....
  }

Dictionary size is already too big. I think it is better not doing 
about change.

Thank you
Masaharu Goto



>Dear Masaharu,
>
>I found some discrepancy between CINT and C++
>
>
>root [2] tn = new TNamed("AAA","BBB")
>root [3] tn->GetName()
>(Text_t* 0x85eb55c)"AAA"       // It is correct
>root [4] tn->TObject::GetName()
>(Text_t* 0x85eb55c)"AAA"       // It is incorrect
>
>C++ gives
> AAA for first case;
> TNamed for second;
>
>Is it hard to fix, or may be there is some workaround?
>
>Generally I need to call method of base class in CINT or by 
>G__ClassInfo family.
>
>Victor
>
>-- 
>Victor M. Perevoztchikov   perev@bnl.gov  perev@vxcern.cern.ch       
>Brookhaven National Laboratory MS 510A PO Box 5000 Upton NY 11973-5000
>tel office : 631-344-7894; fax 631-344-4206; home 631-345-2690



This archive was generated by hypermail 2b29 : Tue Jan 04 2000 - 00:43:43 MET