简体   繁体   中英

Polymorphism or inheritance?

I have a theoretical question about C++. It was part of the final exam at my university and I want to know why the method f of class B is called, while it should be derived by the base class A . Since it is not virtual shouldn't the A::f() be called?

#include <iostream.h>
#include <stdlib.h>

class A{
     public:int f(int x){
               cout<< x << " ";
     }
};
class B:public A{
     public:int f(int y){
                A::f(y+1);
     }
};
void g(A a, B b) {
       a.f(3);
       b.f(3);
 }

int main()
{
  B p; 
  B q; 
  g(p,q);
  system("PAUSE");
  return 0;
}

// result is 3 4

The static type if b in g() is B , thus there is no need for virtual here - the compiler can know [at compile time] you want to invoke B::f() , and that is exactly what he is doing.
In here, the class B redefined A 's f() , and hides it, so invoking f() from a variable whose static type is B results in invoking B::f()

Note that the virtual keyword allows you to use overriding methods where the static type is the parent's type.

The method g takes two arguments, of type A and B repsectively. Since these are no pointer or reference types, dynamic binding does not apply. The compiler knows at compile time the actual type of the objects, and does a static method call.

virtual methods only apply if you have pointers or references!

The function int f(int) in class B "hides" the function with the same name and signature in its base class.

So, when you call bf(3); , and the variable b has type B , you are calling B::f .

Virtual functions are only needed if you want bf(3) to call B::f in cases where the type of the variable b is A& , but the object it refers to has runtime type B . In that situation, the function called would be B::f if A::f is virtual, but A::f is called if non-virtual.

Virtual function calls take the runtime type of objects into account even if they're used via a pointer or reference to a base class. But B b; bf(3) B b; bf(3) is a call to B::f regardless of whether A::f even exists, never mind whether it's virtual or non-virtual.

"Non-scientific" explanation:

The function g treats a as if it was an instance of A gets a copy of p as an object of type A (see comments below) , and executes the f from within A . b is treated as an instance of B , where the method Bf overrides Af , so when b is "looked at" as an instance of B and we execute bf , the method Bf will be executed, because the Af is not visible

If you'd like to call Af using bf you'd have to cast b to A : ((A)b).f() .

There are 2 things happening here:

  1. You are slicing your object.
  2. Your f() function is not an override because it is not virtual, and really you should not be doing this.

You would overcome the slicing by making the function g take its first parameter by reference. If A was given a protected copy-constructor that would also prevent it, although then you would not be able to copy genuine instances of A.

In this case your function g will always call A::f() even with reference to A because there is no polymorphism. To invoke that you will need to declare A::f() as virtual.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM