3

I am having some unexpected behavior when using references on virtual methods. Basically if I take a reference to an object of the base class, then change that reference to an object of the derived class. When I call the virtual method, the base class method is called.

But if I take a reference to the base class and initialize it to the derived class, the derived method is called. Here is some code.

// A base class with a virtual that prints the class
class BaseClass {
    public:
            virtual void printMe();
};

class DerivedClass : public BaseClass {
    public:
            void printMe() override;
};

void BaseClass::printMe() {
    cout << "in Base"<<endl;
}

void DerivedClass::printMe() {
    cout << "in Derived"<<endl;
}


int main () {
    BaseClass bc = BaseClass();
    DerivedClass dc = DerivedClass();

    BaseClass * pbc = & bc ;
    pbc->printMe();            // Prints in Base
    pbc = & dc;
    pbc->printMe();            // Prints in Derived

    // Now with a reference
    BaseClass & bcr = bc;
    bcr.printMe();              // Prints in Base
    bcr = dc;
    bcr.printMe();              // Prints in Base   !!! 

    BaseClass & foo = dc;
    foo.printMe();              // Prints in Derived !!!
    return 0;
}

if someone could explain why the fourth print is not "in Derived" and why the fifth one is "in Derived" I would be grateful.

I (now) understand what has been posted about slicing - but under that logic I don't understand why

BaseClass & foo = dc;
foo.printMe()

calls the derived method

Nevermind I see it now.

Cœur
  • 37,241
  • 25
  • 195
  • 267

2 Answers2

1

References must be initialized, but can never be assigned.

That means when you do: bcr = dc;, you're not making bcr refer to dc. Rather, you're taking the value of dc, "slicing" it to create a temporary object of the base class, and then assigning that temporary to the object to which bcr refers (which is bc). Afterwards, dcr still refers to bc, and bc has been assigned a new value (from the base class sub-object of dc).

Once a reference refers to one object (which must happen as the reference is create) it can/will always refer to that object. Any attempt at assignment will assign to that object to which it refers, not to the reference itself.

Jerry Coffin
  • 476,176
  • 80
  • 629
  • 1,111
1

This:

bcr = dc;

will not assign dc to bcr.

It will perform Slicing. It will chop off all the extra things the derived class has in comparison to the base class (it will treat the derived class like a base class in other words).

gsamaras
  • 71,951
  • 46
  • 188
  • 305