为什么这个虚方法返回true?

Jam*_* Ko 2 c++ polymorphism virtual reference

在学习C++中的多态性教程时,我的一些代码似乎在调用非重写虚拟方法时表现得很奇怪.以下是课程:

// 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;
}
Run Code Online (Sandbox Code Playgroud)

这是主要方法:

// 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;
}
Run Code Online (Sandbox Code Playgroud)

运行时,此代码将打印1 1 1(true true true); c.has_eyesight()如果它引用的是C而不是See,则不应该返回false?

(请原谅我,如果这听起来很幼稚,我刚开始学习C++.)

Ebo*_*ike 7

让我们来看看你在这里做的事情.

C& c = si;
Run Code Online (Sandbox Code Playgroud)

c现在是一个引用Classes::si,这是一个实例See.所以它的vtable指向那个See,has_eyesight()并将返回true.

引用和指针之间的主要区别在于您无法修改其目标 - 无论您做什么,c现在都会始终指向Classes::si它.含义...

c = Classes::c;
Run Code Online (Sandbox Code Playgroud)

这不会改变对引用的引用Classes::c.您无法修改参考.相反,它在c上调用赋值运算符,所以现在你要复制Classes::cClasses::si.除非你超载operator=,否则这将成为逐个成员的副本.它不会修改vtable,因此has_eyesight()将继续返回true.

如果你想让它指向别的东西,你将不得不使用指针:

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;
Run Code Online (Sandbox Code Playgroud)

试试这个.