Reference variable and virtual functions
Asked Answered
M

2

6

I've found a strange behavior while using a reference variable.

Here is class implementations:

class Base {
    public:
        virtual void Method() = 0;
};

class DerivedA : public Base {
    public:
        virtual void Method() {}
}

class DerivedB : public Base {
    public:
        virtual void Method() {}
}

Here is an example code which have the strange behavior:

void main(int argc, char *argv[]) {
    DerivedA a;
    DerivedB b;
    Base &base = a;

    base.Method();   // Calls DerivedA::Method

    base = b;
    base.Method();   // Calls DerivedA::Method!!! Why doesn't call DerivedB.Method()?
}

In conclusion, it seems that the virtual function pointer table "associated" to the reference variable is determine only when initializing the reference variable. If I re-assign the reference variable the vfpt doesn't change.

What happens here?

Mentalism answered 3/12, 2011 at 10:39 Comment(0)
L
13

Base &base is a reference, i.e. alias to the a object, so the assignment base = b is equivalent to a = b, which leaves the base thingie still the same object of the same class. It is not a reassignment of pointer as you seem to assume.

Letterperfect answered 3/12, 2011 at 10:42 Comment(2)
I think this answer deserves the green tick!Bunnybunow
Thanks, though accepted answer is the one questioner has accepted and it's okay that he accepted the other answer ;-)Letterperfect
E
7

References can only be initialized once. You can not assign a new object to a reference. What is actually happening here is that operator= of Base is called and the underlying object is still DerivedA and not DerivedB.

Eventide answered 3/12, 2011 at 10:43 Comment(5)
I am not sure this is correct actually. The operator= is not defined in Base, so there is nothing to call really, apart from C++ default implementation of operator=. I think what is happening here is what @MichaelKrelin answered below.Fortunetelling
@Fortunetelling As you wrote, there's the default implementation of operator=. The default implementation is not virtual and the type of base is Base so Base::operator=() is called. Michael answer is correct too. The two answers do not contradict each other.Eventide
This answer contradicts neither my answer nor the truth. The only thing that bothers me is how is it important that the default operator= implementation is not virtual? ;-)Letterperfect
@MichaelKrelin-hacker Just noting that which operator is to be called is dependent only on the type of the reference and not dependent on the type of the object.Eventide
Yeah, though was it to depend on the type of the reference it still would be a's operator= ;-)Letterperfect

© 2022 - 2024 — McMap. All rights reserved.