Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why does this virtual method return true?

While taking a tutorial on polymorphism in C++, I some code that seems to be acting strangely on the call to a non-overriden virtual method. Here are the classes:

// classes.cpp

namespace Classes
{
    class C
    {
    public:
        virtual bool has_eyesight()
        {
            return false;
        }
    } c;

    class See : public C
    {
    public:
        bool has_eyesight() override
        {
            return true;
        }
    } si;
}

And here is the main method:

// file.cpp

#include <iostream>
#include "classes.cpp"

using std::cout;
using std::endl;
using Classes::C;
using Classes::See;

int main()
{
    See& si = Classes::si;

    cout << si.has_eyesight() << endl;

    C& c = si;

    cout << c.has_eyesight() << endl;

    c = Classes::c;

    cout << c.has_eyesight() << endl;
}

This code will print 1 1 1 (true true true) when run; shouldn't c.has_eyesight() return false if it references a C and not a See?

(Forgive me if this sounds naive, I just started learning about C++.)

like image 210
James Ko Avatar asked Jan 21 '26 15:01

James Ko


2 Answers

Let's go through what you're doing here.

C& c = si;

c is now a reference to Classes::si, which is an instance of See. So its vtable points to that of See, and has_eyesight() will return true.

The main difference between a reference and a pointer is that you can't modify its target - c will now ALWAYS point to Classes::si, no matter what you do. Meaning...

c = Classes::c;

This will not change the reference to Classes::c. You cannot modify a reference. Instead, it calls the assignment operator on c, so now you're copying Classes::c over Classes::si. Unless you overload operator=, this will do a member-by-member copy. It will not modify the vtable, so has_eyesight() will continue to return true.

If you do want to make it point to something else, you will have to use a pointer:

See* si = &Classes::si;
cout << si->has_eyesight() << endl;
C* c = si;
cout << c->has_eyesight() << endl;
c = &Classes::c;
cout << c->has_eyesight() << endl;

Try this.

like image 135
EboMike Avatar answered Jan 23 '26 08:01

EboMike


The code

c = Classes::c;

is not reassigning the reference. Reassigning the reference is impossible in c++. Instead it does assignment for the underlying value.

like image 29
tp1 Avatar answered Jan 23 '26 08:01

tp1



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!