Перегрузка функций
Часть раздела Объектно-ориентированное программирование путешествия по C++ на Coddy. Урок 57 из 104.
Перегрузка функций позволяет define несколько функций с одним и тем же именем, но разными списками параметров. Компилятор выбирает подходящую версию на основе переданных вами аргументов. Это одна из ключевых форм полиморфизма времени компиляции.
Чтобы перегрузка работала, функции должны отличаться своей сигнатурой — количеством parameters, их типами или и тем, и другим:
class Calculator {
public:
int add(int a, int b) {
return a + b;
}
double add(double a, double b) {
return a + b;
}
int add(int a, int b, int c) {
return a + b + c;
}
};
Calculator calc;
calc.add(5, 3); // Вызывает add(int, int)
calc.add(2.5, 3.7); // Вызывает add(double, double)
calc.add(1, 2, 3); // Вызывает add(int, int, int)Компилятор проверяет каждый вызов и сопоставляет его с подходящим overload. Это происходит полностью во время компиляции, поэтому накладных расходов во время выполнения нет.
Важно: Один только тип return не отличает перегруженные функции. Следующее вызовет ошибку компилятора:
int getValue();
double getValue(); // Ошибка: нельзя перегружать только по типу возвращаемого значенияПерегрузка функций делает ваш код более понятным. Вместо создания отдельных имён, таких как addInts, addDoubles и addThreeInts, используйте одно содержательное имя и позвольте компилятору позаботиться обо всём остальном.
Задание
ЛегкоДавайте создадим класс форматирования сообщений, демонстрирующий возможности overload функций. Вы создадите класс Formatter с несколькими методами format(), которые обрабатывают разные типы входных данных, позволяя компилятору выбирать подходящую версию в зависимости от переданных вами аргументов.
Вы организуете код в двух файлах:
Formatter.h: определите классFormatterс перегруженными методамиformat(), обрабатывающими разные сценарии:- метод, который принимает одну строку
std::stringи выводит:Message: <text> - метод, который принимает
std::stringи приоритет уровняint, выводя:[Priority <priority>] <text> - метод, который принимает
std::stringи временную меткуdouble, выводя:[<timestamp>s] <text> - метод, который принимает три параметра
std::string(sender, receiver, message) и выводит:From <sender> to <receiver>: <message>
format(): компилятор выберет правильный из них на основе аргументов.- метод, который принимает одну строку
main.cpp: прочитайте четыре входных значения (каждое в отдельной строке):- простой текст сообщения
- уровень приоритета (целое число)
- временная метка (число с плавающей точкой)
- имя отправителя
Создайте объект
Formatterи продемонстрируйте все четыре перегруженных метода:- вызовите
format(), передав только текст сообщения - вызовите
format(), передав текст сообщения и приоритет - вызовите
format(), передав текст сообщения и временную метку - вызовите
format(), передав отправителя, "Admin" в качестве получателя и текст сообщения
Например, при входных данных System ready, 3, 12.5 и Server:
Message: System ready
[Priority 3] System ready
[12.5s] System ready
From Server to Admin: System readyОбратите внимание: вы вызываете одно и то же имя метода format() четыре раза, но каждый вызов обращается к отдельной версии в зависимости от типов и количества аргументов. Это полиморфизм времени компиляции в действии: компилятор определяет, какой overload использовать, ещё до запуска программы.
Попробуйте сами
#include <iostream>
#include <string>
#include "Formatter.h"
using namespace std;
int main() {
// Считать входные данные
string message;
getline(cin, message);
int priority;
cin >> priority;
double timestamp;
cin >> timestamp;
cin.ignore();
string sender;
getline(cin, sender);
// TODO: Создать объект Formatter
// TODO: Вызвать format() только с текстом сообщения
// TODO: Вызвать format() с текстом сообщения и priority
// TODO: Вызвать format() с текстом сообщения и timestamp
// TODO: Вызвать format() с sender, "Admin" в качестве получателя и текстом сообщения
return 0;
}
В этом уроке есть небольшой тест. Начните урок, чтобы ответить на вопросы и сохранить прогресс.
Все уроки раздела Объектно-ориентированное программирование
1Основы ООП
Внешние файлыСборка и компиляция C++Заголовочные файлы и файлы исходного кодаПространства имен и область видимостиВведение в ООП на C++Классы и объектыУказатель 'this'Методы (функции-члены)Атрибуты (члены данных)Основы конструкторов и деструкторовИтоги — Простой калькулятор4Свойства классов
Члены экземпляра против статическихГеттеры и сеттерыКонстантные функции-членыКлючевое слово mutableСтатические методы и переменныеДружественные функции и классыИтоги — Менеджер банковских счетов7Наследование
Основы наследованияУровни доступа при наследованииПорядок вызова конструкторов и деструкторовПереопределение методовВиртуальные функции и VTableМножественное наследованиеВиртуальное наследованиеИтоги — Иерархия сотрудников10Обзор STL
Обзор и философия STLКонтейнеры STLИтераторыАлгоритмы STLФункторы и лямбда-выраженияИтоги: частота слов13Паттерны проектирования. Часть 1
Введение в паттерны проектированияПаттерн SingletonFactory и Abstract FactoryПаттерн BuilderПаттерн ObserverПаттерн Strategy2Управление памятью
Стек и кучаУказатели и ссылкиДинамическая память (new/delete)Умные указатели в C++RAII в C++Итоги — Менеджер динамического массива5Инкапсуляция
Спецификаторы доступа в C++Спецификаторы доступа: подробный разборСокрытие данныхStruct против ClassВложенные и внутренние классыИтоги — Система учета студентов8Полиморфизм
Полиморфизм компиляции и времени выполненияПерегрузка функцийВиртуальные функции: повторениеЧистые виртуальные функцииАбстрактные классыПроектирование интерфейсов на C++Dynamic Casting и RTTIИтоги: Калькулятор фигур11Продвинутые концепции ООП
Композиция против наследованияМиксины через CRTPИдиома PimplСтирание типовEnum Classes и строгая типизацияОбработка исключений в ООППользовательские иерархии исключений14Паттерны проектирования. Часть 2
Паттерн КомандаПаттерн АдаптерПаттерн ДекораторПаттерн Шаблонный методПаттерн СостояниеПаттерн КомпоновщикRAII как паттерн3Конструкторы и деструкторы
Конструктор по умолчаниюПараметризованный конструкторКонструктор копированияКонструктор перемещенияСписки инициализации конструктораДелегирующие конструкторыГлубокое погружение в деструкторыПравило трех / пяти / нуляПовторение — класс String6Перегрузка операторов
Введение в перегрузку операторовПерегрузка арифметических операторовПерегрузка операторов сравненияОператоры потоковПерегрузка оператора присваиванияПерегрузка операторов [] и ()Операторы преобразования типовИтоги — класс Matrix9Шаблоны
Шаблоны функцийШаблоны классовСпециализация шаблоновВариативные шаблоныОсновы SFINAE и Type TraitsИтоги — Обобщенный контейнерПотренируйтесь самостоятельно: Онлайн-компилятор C++