这只是一个实验代码。
struct B
{
virtual B* operator -> () { return this; }
void foo () {} // edit: intentionally NOT virtual
};
struct D : B
{
virtual D* operator -> () { return this; }
void foo () {}
};
int main ()
{
B &pB = *new D;
pB->foo(); // calls B::foo() !
}
我知道必须使用对象或引用来调用operator
;因此,在上述情况下,参考pB
仍然坚持B
的对象?
虽然它不实用,但出于好奇,有没有办法通过D::operator ->
调用pB
?
答案 0 :(得分:8)
我认为 正在调用D::operator->
,但返回值被视为B*
,因此正在调用B::foo()
。
这是协变返回类型表现的工件。
答案 1 :(得分:2)
pB
的类型为B&
。因此,在其上调用的任何方法(例如operator->
)都将在B
中获得签名,因此pB.operator->()
将返回B*
。当然,因为它是虚拟的,所以使用D
中的实际实现。重要的是返回类型由pB变量的类型定义。
因此,我们的operator->
已返回B*
,因此调用foo()
的行为与任何其他B*
一样。
答案 2 :(得分:1)
它调用哪个运算符(在这种情况下可能是D::operator->
)并不重要,重要的是this
。在这种情况下,this
指针的类型为B*
,因此foo
调用将取消引用至B::foo
。如果它是virtual
- 它会正常工作,但你故意没有成功virtual
......
答案 3 :(得分:1)
根据调用中使用的对象的动态类型调用虚拟成员函数。根据调用中使用的对象的 static 类型调用非虚拟成员函数。
功能foo
不是虚拟的。这意味着它总是根据对象的 static 类型调用。在这种情况下,静态类型为B
(因为B::operator ->
的结果的声明类型为B *
),因此调用B::foo
。