MiddleДебаггингЧастоЕщё не отвечали
Какие подводные камни у дефолтных аргументов в виртуальных функциях и между TU?
Вызов f() через Base* выполняет Derived::f, но печатается аргумент 1, а не ожидаемый автором 2. Поведение удивляет любого читателя.
struct Base {
virtual void f(int x = 1) { std::cout << "Base " << x << '\n'; }
};
struct Derived : Base {
void f(int x = 2) override { std::cout << "Derived " << x << '\n'; }
};
void call(Base* b) { b->f(); } // печатает "Derived 1"
Найдите ошибку и объясните причину.
Дефолты привязываются статически по типу указателя/ссылки. Base* b = new Derived; b->f(); берёт дефолт Base, хотя выполняется Derived::f.
- ✗Переопределить virtual с другим дефолтом — вызов берёт дефолт базового класса
- ✗Разные дефолты в двух заголовках — нарушение ODR
- ✗Дефолты, зависящие от глобалов — неочевидное поведение в точке вызова
- →Почему стандарт выбрал статическое связывание для дефолтов?
- →Как
std::optional/ sentinel чисто заменяют дефолтные аргументы?