Статически выбранная функция и виртуальная функция

Недавно я видел этот стандартный абзац 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.

Как выражение вызова может на самом деле вызывать функцию другого выбранного типа?

Неуклюжая формулировка, напоминающая читателю, что поиск имени, разрешение перегрузки и определение типов выражений выполняются во время компиляции, поскольку C++ является языком статического типа. Нет необходимости напоминать читателю о std, поскольку это предполагается практически повсеместно. Очевидно, что поиск имени не может быть выполнен в динамическом типе вычисляемого выражения. Контроль доступа также учитывает статические типы. Шаблоны также не создаются во время выполнения!

curiousguy 21.09.2018 04:58
Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
2
1
83
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

виртуальные функции могут иметь ковариантный тип возврата,

так с

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, и его тип возврата - B*. Даже если при переопределении f указанный тип возвращаемого значения является ковариантным (D*). Тот факт, что фактический вызов (предположительно) разрешен во время выполнения, не меняет того факта, что мы статически выбираем личность функции. Это уместно, когда есть перегрузка. Одно и то же имя функции может обозначать две или более функций, и это разрешение перегрузки, которое (статически) выбирает, какую перегрузку вызывать. Эта перегрузка может быть переопределена в производном классе, но опять же ее идентификатор статичен.

Я выбрал этот как принятый, потому что он действительно помогает понять, что означает statically chosen function. Спасибо.

stryku 20.09.2018 14:43

Другие вопросы по теме