В чем разница между перегрузкой функций и виртуальными функциями в C++?

«В чем разница между перегрузкой функций и виртуальными функциями в C++?» — вопрос из категории ООП, который задают на 25% собеседований C/C++ Разработчик. Ниже — развёрнутый ответ с разбором ключевых моментов.

Ответ

Это два разных механизма, реализующих разные виды полиморфизма.

Перегрузка функций (Function Overloading) — Статический (compile-time) полиморфизм.

  • Что это: Несколько функций в одной области видимости (например, в одном классе) имеют одинаковое имя, но разные параметры (тип, количество, порядок).
  • Когда разрешается: Компилятор выбирает нужную функцию на этапе компиляции, основываясь на типах переданных аргументов.
  • Пример:
    
    void print(int value) { std::cout << "Integer: " << value; }
    void print(const std::string& value) { std::cout << "String: " << value; } // Перегрузка
    void print(double value, int precision); // Ещё одна перегрузка

print(10); // Вызовет print(int) print("Hello"); // Вызовет print(const std::string&)


### Виртуальные функции (Virtual Functions) — **Динамический (runtime) полиморфизм**.
*   **Что это:** Функция в базовом классе, объявленная с ключевым словом `virtual`, которая может быть **переопределена (override)** в производных классах.
*   **Когда разрешается:** Конкретная вызываемая функция определяется **во время выполнения** на основе фактического типа объекта, на который указывает ссылка или указатель.
*   **Пример:**
```cpp
class Shape {
public:
    virtual void draw() const { // Виртуальная функция
        std::cout << "Drawing a generic shape.n";
    }
    virtual ~Shape() = default; // Виртуальный деструктор — must have!
};

class Circle : public Shape {
public:
    void draw() const override { // Переопределение виртуальной функции
        std::cout << "Drawing a circle.n";
    }
};

int main() {
    Circle circle;
    Shape& shapeRef = circle; // Ссылка базового типа на объект производного типа
    shapeRef.draw(); // Вызовется Circle::draw() (динамическое связывание)
    return 0;
}
Сводная таблица различий: Критерий Перегрузка Виртуальные функции
Тип полиморфизма Статический (compile-time) Динамический (runtime)
Основа выбора Сигнатура функции (параметры) Фактический тип объекта
Область действия Один класс/область видимости Иерархия наследования
Ключевые слова Не требуются virtual, override (C++11)
Связывание Раннее (early binding) Позднее (late binding) через vtable