静态选择函数和虚函数

Statically chosen function and virtual function

最近看到这个C++标准段(http://eel.is/c++draft/expr.post#expr.call-5):

If the postfix-expression designates a destructor, the type of the function call expression is void; otherwise, the type of the function call expression is the return type of the statically chosen function (i.e., ignoring the virtual keyword), even if the type of the function actually called is different. This return type shall be an object type, a reference type or cv void.

这部分我不是很明白:

the type of the function call expression is the return type of the statically chosen function (i.e., ignoring the virtual keyword), even if the type of the function actually called is different.

  1. 这里静态选择的函数是什么?
  2. 如何静态选择虚函数?我一直以为是运行时选择的
  3. even if the type of the function actually called is different.

调用表达式如何实际调用所选不同类型的函数?

虚函数可以有协变return类型,

所以

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

先举个例子来说明。

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,它的 return 类型是 B*。即使在覆盖 f 时指定的 return 类型是协变的 (D*)。实际调用(假定)在 运行 时间解析的事实并没有改变我们静态选择函数的 身份 的事实。当还涉及超载时,这是相关的。相同的函数名称可以指定两个或多个函数,并且(静态地)选择要调用哪个重载的是重载决策。该重载可能会在派生 class 中被覆盖,但它的标识同样是静态的。