Люди уже определили как перегрузку, так и переопределение, поэтому я не буду уточнять.
ASAFE спросил:
единственное преимущество [перегрузки] в том, что вы не думаете о нескольких именах функций?
1. Вам не нужно думать под несколькими именами
И это уже мощное преимущество, не так ли?
Давайте сравним с известными функциями C API и их вымышленными вариантами C ++:
/* C */
double fabs(double d) ;
int abs(int i) ;
// C++ fictional variants
long double abs(long double d) ;
double abs(double d) ;
float abs(float f) ;
long abs(long i) ;
int abs(int i) ;
Это означает две вещи: во-первых, вы должны указать компилятору тип данных, которые он будет передавать в функцию, выбрав правильную функцию. Во-вторых, если вы хотите расширить его, вам нужно будет найти причудливые имена, а пользователь ваших функций должен будет запомнить правильные причудливые имена.
И все, что он / она хотел, это иметь абсолютное значение некоторой числовой переменной ...
Одно действие означает одно и только одно имя функции.
Обратите внимание, что вы не можете изменять тип одного параметра. Все может измениться, если это имеет смысл.
2. Для операторов обязательно
Давайте посмотрим на операторов:
// C++
Integer operator + (const Integer & lhs, const Integer & rhs) ;
Real operator + (const Real & lhs, const Real & rhs) ;
Matrix operator + (const Matrix & lhs, const Matrix & rhs) ;
Complex operator + (const Complex & lhs, const Complex & rhs) ;
void doSomething()
{
Integer i0 = 5, i1 = 10 ;
Integer i2 = i0 + i1 ; // i2 == 15
Real r0 = 5.5, r1 = 10.3 ;
Real r2 = r0 + r1 ; // r2 = 15.8
Matrix m0(1, 2, 3, 4), m1(10, 20, 30, 40) ;
Matrix m2 = m0 + m1 ; // m2 == (11, 22, 33, 44)
Complex c0(1, 5), c1(10, 50) ;
Complex c2 = c0 + c1 ; // c2 == (11, 55)
}
В приведенном выше примере вы хотите, чтобы не использовал ничего, кроме оператора +.
Обратите внимание, что в C имеется неявная перегрузка операторов для встроенных типов (включая сложный тип C99):
/* C */
void doSomething(void)
{
char c = 32 ;
short s = 54 ;
c + s ; /* == C++ operator + (char, short) */
c + c ; /* == C++ operator + (char, char) */
}
Так что даже в необъектных языках эта вещь перегрузки используется.
3. Для объектов обязательно
Давайте рассмотрим использование объекта базовыми методами: его конструкторы:
class MyString
{
public :
MyString(char character) ;
MyString(int number) ;
MyString(const char * c_style_string) ;
MyString(const MyString * mySring) ;
// etc.
} ;
Некоторые могут рассматривать это как перегрузку функций, но на самом деле это больше похоже на перегрузку операторов:
void doSomething()
{
MyString a('h') ; // a == "h" ;
MyString b(25) ; // b == "25" ;
MyString c("Hello World") ; // c == "Hello World" ;
MyString d(c) ; // d == "Hello World" ;
}
Вывод: перегрузка это круто
В C, когда вы даете имя функции, параметры неявно являются частью подписи при вызове. Если у вас есть «двойные fabs (double d)», то, хотя подпись fabs для компилятора - это неокрашенные «fabs», это означает, что you должен знать, что для этого требуется только удвоение.
В C ++ имя функции не означает, что ее подпись является принудительной. Его подпись при вызове - это его имя и параметры. Таким образом, если вы напишите abs (-24), компилятор будет знать, какую перегрузку abs он должен вызвать, и вы, при его написании, найдете это более естественным: вам нужно абсолютное значение -24.
В любом случае, любой, кто хоть немного кодировал на любом языке с операторами, уже использует перегрузку, будь то C или Basic числовые операторы, конкатенация строк Java, делегаты C # и т. Д. Почему? потому что это более естественно .
А приведенные выше примеры являются лишь верхушкой айсберга: при использовании шаблонов перегрузка становится очень и очень полезной, но это уже другая история.