Link to home
Start Free TrialLog in
Avatar of yuxiliu
yuxiliu

asked on

Virtual & Overide?

Now I know override will hide overload member functions in BASE class, there is a furture more question, what happened when I mark fun() as "virtual" like following,
This should generate a "VTBL" for BASE and Derived class but why the override sitll hides overloaded member functions in BASE class???

1 #include <stdio.h>
3
4 class BASE
5 {
6 public:
7 BASE() {};
8 ~BASE() {};
9 virtual fun() { cout << " BASE fun()" << endl; } ;
10 virtual fun(int ) { cout << " BASE fun(int)" << endl; } ;
11 virtual fun(int , int) { cout << " BASE fun(int )" << endl; } ;
12 };
13
14 class DERIVED: public BASE
15 {
16 public:
17 DERIVED() {};
18 ~DERIVED() {};
19 fun() { cout << " DETRIVED fun()" << endl; } ;
20 };
21
22
23 int main()
24 {
25 DERIVED *d1= new DERIVED();
26 BASE *d2= new DERIVED();
27
28 d1->fun(1);  //Compile Error... Why??? fun is Virtual now
29
30 d2->fun(1);  //OK
31 return 0;
32 }





ASKER CERTIFIED SOLUTION
Avatar of nietod
nietod

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Avatar of nietod
nietod

Now consider

>> d2->fun(1);  //OK

In this case the pointer is a pointer to a BASE object, so the compiler performs a search in the scope of the BASE class.  (And no matter what, it will end the search there too, since there are no class scopes outside of that class.)  In this case it finds a function called fun, so it then stops the search for functions in the scope of the BASE class.  It then looks for a function whose signature matches the invokation.  In this case it finds

virtual fun(int ) { cout << " BASE fun(int)" << endl; } ;


continues
class B
{
public:  
   void fun() { cout << "B:fun()"; }
   void fun(int i) { cout << "B:fun(int)"; }
};

class D1 : public B
{
public:  
   void fun(int) { cout << "D1:fun(int)"; }
};

class D2 : public D1
{
public
void AFunction();
};

consider what the compiler does when it encouters the following in AFunction.

void D2::AFunction()
{
  fun(5);
}

The object is a D2 object, so the compiler starts searching for the function in the scope of the D2 class.    There is no function called "fun" in that scope.  So it proceeds to the outer scope.  This is the D1 scope.  It does find a function called "fun" in this scope.  So now the search for fucntions ends in this scope.  The compiler then looks for the function in this scope, in D2, that matches the signature of the invocation.  However, there is none, so the program is ill-formed.  

No consider.

void D2::AFunction()
{
  fun(5);
}

The object is a D2 object, so the compiler starts searching for the function in the scope of the D2 class.    There is no function called "fun" in that scope.  So it proceeds to the outer scope.  This is the D1 scope.  It does find a function called "fun" in this scope.  So now the search for functions ends in this scope..  The compiler then looks for the function in this scope, in D2, that matches the signature of the invocation.  It finds "fun(int)" , so there is a match.  sot he program is fine.


continues
Now code like

D2 d2;

d2->fun(5); // Okay;
d2->fun(); // Error.

is the same.  The compiler still searches beginnign with the scope of the D2 class and then continues to the other scopes only if it finds no functions that have the name "fun"  Once any scope is found that has any function of the target name, the search will stop (in success or in failure) with the scope that contains that name.  This is true even if there is an outer scope that does supply the right signature function.


Note that this search has NOTHING to do with virtual functions in any way.  The compiler is simply searching to see if a function exists with the specified name and signature and that the function is accessable (not private for example).  If the function is virtual, the exact override that will be called will be dermined at run-time (unless the compiler can determine it at compile time, often it is possible to do so.)  but that is a seperate issue.  Before it can consider the virtual aspect of the function, it needs to find a declation for the function and for that it must perforn the search I outlined.

continues
Now you can get around this by using a "using declaration"   Like  In your code you could use

class DERIVED: public BASE
{
public:
   DERIVED() {};
   ~DERIVED() {};

   using BASE::fun;  // Bring the "fun" names in from the BASE class

   fun() { cout << " DETRIVED fun()" << endl; } ;
};

This brings the names of the "fun" functions from the BASE scope to the DERIVED scope.  This allows the compiler's search to find all the "fun()" names that were declared in BASE in the scope of the DERIVED class.
Has this answered your question?