2

I have a Rabbit struct, and CrazyRabbit struct that inherits it. When I execute this code:

#include <iostream>

using namespace std;

struct Rabbit {
    virtual void sayCry() { 
        cout << "..." << endl; 
    } 
};

struct CrazyRabbit : Rabbit { 
    void sayCry() { cout <<"Moo"<< endl; }
};

void foo(Rabbit r, Rabbit* pr, Rabbit& rr) { 
    r.sayCry();
    pr->sayCry(); 
    rr.sayCry();
}

int main(int argc, char *argv[]) {
    Rabbit *pr = new CrazyRabbit(); 
    foo(*pr, pr, *pr);
}

I have the results:

...
Moo
Moo

Why the first case executes the method in super class? Is there any rule for execution defined in C++?

prosseek
  • 182,215
  • 215
  • 566
  • 871

2 Answers2

1

foo()'s first argument type is not a pointer, what you're actually doing is copying into an instance of the superclass. This is because every function parameter gets initialized with whatever you provide as arguments when you actually call the function. So it's as if you had done the following:

Rabbit r = *pr; // (from your main()) object slicing happens here
Rabbit* pr = pr; // (the rhs pr is from your main(), not the pr from foo())
Rabbit& rr = *pr; // (from your main())

So in the first case, you are simply declaring an object of type Rabbit and assigning its derived class, which causes object slicing, meaning that any data that belongs to the derived class CrazyRabbit is lost and the only data that is left is that of the Rabbit type.

For virtual function calls, you require a pointer. At run time, C++ will check the vptr and vtbl to correctly identify which virtual function to call.

bku_drytt
  • 3,169
  • 17
  • 19
1

This is called "Object Slicing", what you are actually doing is to assign a pointer to derived class object to base class type, the compiler will slice off the things so that it matches with the base class type.

Since, here the base class does not know anything about derived class's function cry(), it will slice it off, and after that compiler can only see base class's cry().

in this example: Though you may think objA will have a,b & c but the "c" of derived is sliced by the compiler.It is called UpCasting.

class A
{
public:
    int a, b;
    A()
    {
        a = 10;
        b = 20;
    }

};
class B :public A
{
public:
    int c;
    B()
    {
        c = 30;
    }

};

int main()
{

    A objA;
    B objB;
    objA = objB;
    return 0;
}
Nishant
  • 1,635
  • 1
  • 11
  • 24