Как сделать перегрузку метода c

Обновлено: 07.07.2024

Перегрузка операторов через методы класса очень похожа на перегрузку операторов через дружественные функции. Но при перегрузке оператора через метод класса левым операндом становится неявный объект, на который указывает скрытый указатель *this.

Перегрузка операторов через методы классов

Вспомним, как выглядит перегрузка оператора через дружественную функцию:

Конвертация перегрузки через дружественную функцию в перегрузку через метод класса довольно-таки проста:

Перегружаемый оператор определяется как метод класса, вместо дружественной функции ( Dollars::operator+ вместо friend operator+ ).

Левый параметр из функции перегрузки выбрасывается, вместо него — неявный объект, на который указывает указатель *this.

Внутри тела функции перегрузки все ссылки на левый параметр могут быть удалены (например, dollars.m_dollars становится m_dollars , который неявно ссылается на текущий объект с помощью указателя *this).

Теперь та же перегрузка оператора + , но уже через метод класса:

// Вместо параметра dollars в перегрузке через дружественную функцию здесь неявный параметр, на который указывает указатель *this

Обратите внимание, использование оператора + не изменяется (в обоих случаях dollars1 + 3 ), но реализация отличается. Наша дружественная функция с двумя параметрами становится методом класса с одним параметром, причем левый параметр в перегрузке через дружественную функцию ( &dollars ), в перегрузке через метод класса становится неявным объектом, на который указывает указатель *this.

Рассмотрим детально, как обрабатывается выражение dollars1 + 3 .

В перегрузке через дружественную функцию выражение dollars1 + 3 приводит к вызову функции operator+(dollars1, 3) . Здесь есть два параметра.

В перегрузке через метод класса выражение dollars1 + 3 приводит к вызову dollars1.operator+(3) . Обратите внимание, здесь уже один явный параметр, а dollars1 используется как префикс к operator+ . Этот префикс компилятор неявно конвертирует в скрытый левый параметр, на который указывает указатель *this. Таким образом, dollars1.operator+(3) становится вызовом operator+(&dollars1, 3) , что почти идентично перегрузке через дружественную функцию.

Итак, если мы можем перегрузить оператор через дружественную функцию или через метод класса, то что тогда выбрать? Прежде чем мы дадим ответ на этот вопрос, вам нужно узнать еще несколько деталей.

Не всё может быть перегружено через дружественные функции

Операторы присваивания ( = ), индекса ( [] ), вызова функции ( () ) и выбора члена ( -> ) перегружаются через методы класса — это требование языка C++.

Не всё может быть перегружено через методы класса

На уроке о перегрузке операторов ввода и вывода мы перегружали оператор вывода для класса Point через дружественную функцию:

Однако через метод класса перегрузить оператор мы не сможем. Почему? Потому что при перегрузке через метод класса в качестве левого операнда используется текущий объект. В этом случае левым операндом является объект типа std::ostream. std::ostream является частью Cтандартной библиотеки C++. Мы не можем использовать std::ostream в качестве левого неявного параметра, на который бы указывал скрытый указатель *this, так как указатель *this может указывать только на текущий объект текущего класса, члены которого мы можем изменить, поэтому перегрузка оператора должна осуществляться через дружественную функцию.

Аналогично, хотя мы можем перегрузить operator+(Dollars, int) через метод класса (как мы делали выше), мы не можем перегрузить operator+(int, Dollars) через метод класса, поскольку int теперь является левым операндом, на который указатель *this указывать не может.

Перегрузка операторов через методы класса не используется, если левый операнд не является классом (например, int), или это класс, который мы не можем изменить (например, std::ostream).

Какой способ перегрузки и когда следует использовать?

В большинстве случаев язык C++ позволяет выбирать самостоятельно способ перегрузки операторов.

При работе с бинарными операторами, которые изменяют левый операнд (например, operator+=()), обычно используется перегрузка через методы класса. В этих случаях левым операндом всегда является объект класса, на который указывает скрытый указатель *this.

Унарные операторы обычно тоже перегружаются через методы класса, так как в таком случае параметры не используются вообще.

Для операторов присваивания ( = ), индекса ( [] ), вызова функции ( () ) или выбора члена ( -> ) используйте перегрузку через методы класса.

Для унарных операторов используйте перегрузку через методы класса.

Для перегрузки бинарных операторов, которые изменяют левый операнд (например, operator+=()) используйте перегрузку через методы класса, если это возможно.

Для перегрузки бинарных операторов, которые не изменяют левый операнд (например, operator+()) используйте перегрузку через обычные/дружественные функции.

Даже если в базовом классе метод не был объявлен виртуальным, в производном классе все равно можно объявить другой метод с такой же сигнатурой. Новый метод однако не перекроет метод базового класса. Напротив, говорят, что он скроет метод базового класса. При этом компилятор, решая, какой метод вызвать, всегда будет рассматривать тип данных, на который указывает переменная, как тип данных заданный при ее объявлении!

Скрытие (переопределение) элементов класса – это явное описание в классе-наследнике с новыми характеристиками уже существующих элементов из наследуемого класса.

Переопределено поле MyNumber (в родительском классе имело целочисельный тип, а в производном – дробный). Поле целого типа скрыто новым описанием. Если бы поле MyNumber не было переопределено, то в классе OurClass (производный) по умолчанию было бы доступен только родительское поле MyNumber типа int. А выражение: oc.MyNumber = 5.5; вызывало ошибку типов.

Скрытие поля класса может произойти по ошибке, например программист случайно вводит название поля, которое уже существует в одном из классов, вышестоящих по цепочке наследования.

Если метод скрывает базового класса, то к его определению необходимо добавить ключевое слово new. Этот модификатор подскажет компилятору, что программист знает о факте сокрытия!

Если класс определен как abstract, сделать его экземпляр невозможно. Если метод объявлен с модификатором abstract то этот метод будет рассматриваться как виртуальный и что вы не реализуете этот метод в классе в расчета на то, что он будет перекрыт в производных классах.

Если хотя бы один метод в классе абстрактный, то и весь класс должен быть абстрактным! Кроме того, любой класс, порожденный от абстрактного должен перекрыть его методы.

Запечатанные (sealed) классы и методы можно рассматривать как противоположность абстрактным классам и методам. Объявление класса или метода запечатанным означает что произвести наследование и перекрытие не возможно.

Вызов базовых версий методов

Ключевое слово base явно указывает компилятору, что происходит обращение к методу базового класса.

+ Индексаторы, операции, свойства можно делать виртуальными и перекрывать их по желанию.

+ Поля не могут быть объявлены виртуальными или перекрытыми. Однако можно скрыть базовую версию поля, объявив другое поле с тем же именем в производном классе с модификатором (new). Получить доступ к базовому полю можно через base.[имя_поля].

+ Статические методы не могут быть объявлены виртуальными, но могут быть скрытыми (new). Не имеет смысла объявлять виртуальным статический член вообще!

Перегрузка методов

Пример перегрузки методов: Console.WriteLine();

  • Перегруженные методы различаются по количеству и типу параметров, передаваемых в качестве аргументов в методы.
  • Вы не можете определить более одного метода с одним и тем же именем, порядком и типом аргументов. Это было бы ошибкой компилятора.
  • Компилятор не учитывает тип возвращаемого значения при дифференцировании перегруженного метода. Но вы не можете объявить два метода с одной и той же сигнатурой и другим типом возвращаемого значения. Это вызовет ошибку во время компиляции. Если оба метода имеют одинаковые типы параметров, но разные возвращаемые типы, это невозможно.

Зачем нам метод перегрузки ??

Если нам нужно выполнить одну и ту же операцию по-разному, т.е. для разных входов. В примере, описанном ниже, мы выполняем операцию сложения для разных входов. Трудно найти много разных значимых имен для одного действия.

Различные способы выполнения методов перегрузки
Перегрузка метода может быть сделана путем изменения:

  1. Количество параметров в двух методах.
  2. Типы данных параметров методов.
  3. Порядок параметров методов.

Изменяя количество параметров

// добавляем два целочисленных значения.

public int Add( int a, int b)

// добавляем три целочисленных значения.

public int Add( int a, int b, int c)

int sum = a + b + c;

public static void Main(String[] args)

GFG ob = new GFG();

int sum1 = ob.Add(1, 2);

Console.WriteLine( "sum of the two "

+ "integer value : " + sum1);

int sum2 = ob.Add(1, 2, 3);

Console.WriteLine( "sum of the three "

+ "integer value : " + sum2);

Изменяя типы данных параметров

// добавляем три целочисленных значения.

public int Add( int a, int b, int c)

int sum = a + b + c;

// добавляем три двойных значения.

public double Add( double a,

double b, double c)

double sum = a + b + c;

public static void Main(String[] args)

GFG ob = new GFG();

int sum2 = ob.Add(1, 2, 3);

Console.WriteLine( "sum of the three "

+ "integer value : " + sum2);

double sum3 = ob.Add(1.0, 2.0, 3.0);

Console.WriteLine( "sum of the three "

+ "double value : " + sum3);

Изменяя порядок параметров

public void Identity(String name, int id)

Console.WriteLine( "Name : " + name + ", "

public void Identity( int id, String name)

Console.WriteLine( "Name : " + name + ", "

public static void Main(String[] args)

GFG obj = new GFG();

obj.Identity( "Akku" , 1);

obj.Identity( "Abby" , 2);

Что происходит, когда сигнатура метода одинакова, а тип возвращаемого значения отличается?

Компилятор выдаст ошибку, поскольку одного возвращаемого значения недостаточно, чтобы компилятор выяснил, какую функцию он должен вызвать. Только если оба метода имеют разные типы параметров (поэтому они имеют разную сигнатуру), возможна перегрузка метода.
Пример:


Как сделать перегрузку метода ToString()
Помогите сделать перегрузку метода ToString(), еще чтобы были готовые 3 пациента при запуске, и.

Реализовать перегрузку виртуального метода
В класе class1 реализован открытый виртуальный метод деление двух чисел "a" и "b". Не внося.


Как тут делать перегрузку метода?
Можете обьяснить что от меня хотят? как тут делать перегрузку. Перегрузите метод f из.


Для чего делают перегрузку метода ToString()
Для чего делают перегрузку метода ToString() или других методов, и как она делаеться ?

Читайте также: