众所周知,“仅当调用是通过 引用或指针。”。因此,当我发现解引用运算符也保留了动态绑定(bind)特性时,我感到很惊讶。
#include <iostream>
using namespace std;
struct B {
virtual void say() { cout << "Hello B" << endl; }
};
struct D : B {
void say() override { cout << "Hello D" << endl; }
};
int main() {
D *ptr = new D();
B *p = ptr;
(*p).say();
return 0;
}
输出是
Hello D
问题:编译器如何处理取消引用运算符 *?
我以为是在编译时完成的。因此,当编译器引用指针 p 时,它应该假定 p 指向 B 类型的对象。例如,以下代码
D temp = (*p);
提示
error: no viable conversion from 'B' to 'D'
最佳答案
从表面上看,这是一个有趣的问题,因为没有一元 *
的重载,取消引用会导致 lvalue B
,不是引用类型。然而,即使开始沿着这条推理线走下去也是一个转移注意力的问题:表达式从不 有引用类型,因为引用会立即被删除并确定值类别。从这个意义上说,一元 *
运算符非常像一个返回引用的函数
事实上,答案是您最初的断言是不正确的:动态调度根本不依赖于引用或指针。是引用和指针使您能够防止切片,但是一旦您有一些引用多态对象的表达式,任何旧的函数调用都可以。
还要考虑:
#include <iostream>
struct Base
{
virtual void foo() { std::cout << "Base::foo()\n"; }
void bar() { foo(); }
};
struct Derived : Base
{
virtual void foo() { std::cout << "Derived::foo()\n"; }
};
int main()
{
Derived d;
d.bar(); // output: "Derived::foo()"
}
( live demo )
关于c++ - 为什么取消引用运算符在 C++ 中保留多态性(后期绑定(bind))?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23748057/