最近我看过这个C ++标准段落(http://eel.is/c++draft/expr.post#expr.call-5):
如果postfix-expression指定一个析构函数,则函数调用表达式的类型为void;否则为false。否则,即使实际调用的函数类型不同,函数调用表达式的类型也就是静态选择的函数的返回类型(即忽略虚拟关键字)。此返回类型应为对象类型,引用类型或cv void。
我不太了解这部分:
即使实际调用的函数类型不同,函数调用表达式的类型也是静态选择的函数的返回类型(即忽略virtual关键字)。
即使实际调用的函数类型不同。
调用表达式实际上如何调用所选类型的函数?
答案 0 :(得分:7)
虚拟函数可以具有协变返回类型,
如此
struct Base
{
virtual ~Base() = default;
virtual Base* Clone() const { return new Base(*this); }
};
struct Derived : Base
{
// covariant return type:
Derived* Clone() const override { return new Derived(*this); }
};
然后
Derived d;
Base& b = d;
auto* clonePtr = b.Clone(); // `auto` is `Base`, even if `Derived::Clone` is called.
// runtime type of `clonePtr` is `Derived`
std::unique_ptr<Base> clone(clonePtr); // Done in 2 steps for explanation
答案 1 :(得分:3)
首先,一个例子来说明。
struct B {
virtual B* f() { return this; }
};
struct D : B {
D* f() override { return this; }
};
void bar(B*) {}
void bar(D*) {}
int main() {
D d;
B& b = d;
bar(b.f()); // calls `bar(B*)`
}
在此,后缀表达式b.f
指定一个函数。它是B::f
,返回类型为B*
。即使覆盖f
时,指定的返回类型也是协变(D*
)。实际的调用(据说)在运行时已解决的事实并不会改变我们静态选择函数的 identity 的事实。当还涉及重载时,这才是适当的。相同的函数名称可以指定两个或多个函数,而过载解析是(静态地)选择要调用的过载。可以在派生类中重写该重载,但是其标识再次是静态的。