Как известно, в С можно присваивать адрес функции указателю и затем вызвать функцию с использованием этого указателя. Та же самая возможность имеется и в C++. Однако из-за наличия перегрузки функций этот процесс становится несколько более сложным. Для того, чтобы понимать причину сложностей, для начала рассмотрим инструкцию, присваивающую адрес функции F() указателю p:
p = F;
Если бы это было частью С-программы, то существовала бы одна и только одна функция с именем F(), так что компилятор без труда присвоил бы ее адрес указателю р. Однако в программе на языке C++ функция F() может быть перегружена. В таком случае, каким образом компилятор может знать, какую именно функцию присваивать указателю p? Ответ зависит от того, каким образом объявлен указатель р. В качестве примера рассмотрим следующую программу:
#include <iostream.h>
int F(int a) { return a; }
int F(int a, int b) { return a*b; }
int main()
{
int (*fp)(int a); // указатель на int xxx(int)
fp = F; // указывает на F(int)
cout << fp(5);
return 0;
}
Как показывает данная программа, fp объявлен как указатель на функцию, возвращающую целое число и имеющую один аргумент. C++ использует эту информацию, чтобы выбрать версию F(int а). Если бы fp был объявлен следующим образом:
int (*fp)(int a, int b);
то указателю fp был бы присвоен адрес функции F(int a, int b). Подведем итог. Когда адрес перегруженной функции присваивается указателю на функцию, то именно способ объявления этого указателя определяет, адрес какой из перегруженных функций будет присвоен этому указателю.
Прежде чем перейти к перегрузке операторов, необходимо познакомиться с ключевым словом this языка C++, которое используется во многих перегруженных операторах.
Всякий раз, когда вызывается функция-член, ей автоматически передается указатель на объект, вызывающий данную функцию. Можно получить доступ к этому указателю, используя this. Указатель this служит неявным параметром всех функций-членов. (Функции-друзья не имеют указателя this.) Например, в операторе:
object.f();
функции f() автоматически передается указатель this, указывающий на объект object.
Как известно, функции-члены имеют непосредственный доступ к данным класса. Например, если задан следующий класс:
class C{
int i;
// ... };
то функция-член может присвоить переменной i значение 10, используя следующую инструкцию:
i = 10;
фактически эта инструкция является сокращенной записью следующей инструкции:
this->i = 10;
Для того чтобы увидеть, как работает указатель this, рассмотрим следующую короткую программу:
#include <iostream.h>
class C
{
int i;
public:
void load_i(int val) { this->i = val; } // то же, что и i = val
int get_i() { return this->i; } // то же, что и return i
};
int main()
{
C o;
o.load_i(100);
cout << o.get_i();
return 0;
}
Эта программа выводит на экран число 100.
Хотя рассмотренный пример достаточно тривиален — фактически никто не использует указатель this таким образом — далее будет пояснено, почему использование указателя this имеет большое значение.