在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;
}
以下是主要方法:
// 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;
}
此代码在运行时将打印1 1 1
(true true true);如果引用C而不是See?
c.has_eyesight()
不应返回false
(请原谅我,如果这听起来很幼稚,我刚开始学习C ++。)
答案 0 :(得分:7)
让我们来看看你在这里做的事情。
<ScrollViewer ZoomMode="Enabled" HorizontalScrollBarVisibility="Auto">
<Image x:Name="ImgFoto" Stretch="Uniform"></Image>
</ScrollViewer>
C& c = si;
现在是对c
的引用,Classes::si
是See
的一个实例。所以它的vtable指向See
的vtable,而has_eyesight()
将返回true。
引用和指针之间的主要区别在于您无法修改其目标 - c
现在始终指向Classes::si
,无论您做什么。含义...
c = Classes::c;
这不会更改对Classes::c
的引用。您无法修改参考。相反,它会调用c上的赋值运算符,因此现在您将Classes::c
复制到Classes::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;
试试这个。
答案 1 :(得分:2)
代码
c = Classes::c;
未重新分配参考。在c ++中无法重新分配引用。相反,它会为基础值进行分配。
答案 2 :(得分:1)
对于第二个:
C& c = si;
c
以多态方式访问,因此只有动态类型计数。动态类型c
为See
,因此会选择See::has_eyesight
。
第三个:
c = Classes::c;
它不是重新引用引用,而是将Classes::c
复制到c
本身。参考不能反弹。
答案 3 :(得分:1)
该行
c = Classes::c;
不要将c
更改为引用Classes::c
。相反,该行等同于:
Classes::si = Classes::c;
这不会更改si
的虚拟表格。因此,当您使用
Classes::See::has_eyesight()
cout << c.has_eyesight() << endl;