Ключевое слово this
• При вызове функции-члена класса передается еще один неявный параметр – указатель на объект класса, который вызывает данную функцию. Этот указатель называется this. Это ключевое слово, в частности, используется при перегрузке операций. В общем случае функции-члены класса могут иметь доступ к приватным элементам класса. Например • class c 1{ • int i; • …. • };
Чтобы понять как работает оператор this рассмотрим короткую программу #include
Рассмотрим дополнительно программу, содержащие перегрузку операции ! #include
• • • // конструктор – инициализация нулями Name: : Name() { memset (data, ‘ ’ , sizeof(data) ); } // сохранить специфицированное имя void Name: : Set. Data(char *new. Data) { strcpy(data, new. Data); }
• • • • // перегрузка операции !() показывает , имеются ли данные int Name: : operator!() { return (data[0] = = ‘ ’) } void main(void) { Name name; if(!name) // неявный вызов operator !() name. Set. Data(“ Тестирование программы”); // теперь явный вызов функции operator!() if(!name. operator!()) printf(“Данные присвоены …. n”); }
Перегрузка операций ввода/вывода. Инсерторы и экстракторы Операция << в англоязычной литературе обычно называется inserting (вставка данных в поток), а операция >> - extracting (извлечение данных из потока). • Функции – члены класса, обеспечивающие перегрузку операций <<, мы будем называть инсертором (insertor), а функцию, соответствующую перегрузке операции >>. Будем называть экстрактором (extractor). •
В качестве примера создания функции инсертора рассмотрим класс vector: class vector{ public: int x, y, z; vector (int a, int b, int c) { x=a; y=b; z=c; } • } • •
Чтобы создать функцию-инсертор для этого класса, мы должны определить операцию ввода относительно этого класса, т. е. перегрузить операцию <<. • • obj) // vector инсертор ostream &operator <<(ostream &stream, vector { } stream << obj. x<<”, “; stream << obj. y<<”, “; stream <
Пример работы инсертора: • #include
Общая форма функции инсертора следующая: • ostream &operator <<(ostream &stream, class_type obj) • { • // тело программы • return stream; • } • Используется вариант • stream << obj. x<<”, “; а не cout<< obj. x<<”, “; • так как второй вариант жестко связан с потоком cout, a первый вариант может быть применен к любому потоку.
• В предыдущем примере данные-члены класса vector объявлены как public. Функция – инсертор не может быть членом класса. Для того, чтобы она имела доступ к приватным элементам класса, необходимо объявить ее “другом“ класса. Тогда предыдущий пример будет иметь вид:
• #include
• Для перегрузки функции >> для класса vector можно использовать следующую функциюэкстрактор: • istream &operator >>(istream &stream, vector obj) • { • cout<<”Enter x, y, z: ”; • stream >> obj. x>>obj. y>>obj. z; • • return stream: }
• Так же как и инсертор, функции -экстрактор не может быть членом класса, а поэтому используется как дружественная функция класса.
Пример • • • • #include
• • • • istream &operator <<(istream &stream, vector obj) { cout<<”Enter x, y, z: ”; stream >> obj. x>>obj. y>>obj. z; return stream: } void main(void) { vector a(1, 2, 3); cout<>a; cout<
Дружественные функцииоперации
Дружественными функциями не могут перегружаться операции =, (), [], ->.
• • • • • Пример перегрузки операции + для класса vector с помощью дружественной операции. class vector { int x, y, z; // Три координаты public: friend vector operator + (vector t 1, vector t 2); vector operator+(vector t); void show(void); void assign( int mx, int my, int mz); }; vector operator+(vector t 1, vector t 2) { vector temp; temp. x=t 1. x+t 2. x; temp. y=t 1. y+t 2. y; temp. z=t 1. z+t 2. z; return temp; }
Пример № 2 • • • • • #include
• • • • CL operator+(int i, CL ob) { CL temp; temp. c=ob. c+i; return temp; } void main(void) { CL a; cout<
Ссылки По умолчанию С и С++ передают аргументы функции, используя вызов по значению (call by value). Передача параметра по значению влечет за собой создание копии аргумента. Эта копия используется функцией и может быть изменена, но исходное значение аргумента при этом не меняется. Когда необходимо, чтобы функция изменяла значение аргумента, то параметры объявляются как указатели с использованием символа *.
Пример • • • void swap 1(int *i, int *j) { int tmp=*i; *i=*j; *j=tmp; }
• • • • пример определения функции, имеющей один ссылочные параметры . void swap 2(int &a, int &b) { int tmp=a; a=b; b=tmp; } С вызовом swap 2(a, b); Общий пример: #include
• • • • • void swap(int a, int b) { int tmp=a; a=b; b=tmp; } void swap 1(int *i, int *j) { int tmp=*i; *i=*j; *j=tmp; } void swap 2(int &a, int &b) { int tmp=a; a=b; b=tmp; }
Использование ссылочных переменных для перегрузки унарных операций • Операция ++ в программе не была перегружена дружественной функцией, так как перегрузка требовала использования ссылки. Теперь перегрузку можно осуществить следующим образом: • friend vector operator++(vector &op 1) • { • op 1. x++; • op 1. y++; • op 1. z++; • return op 1; • }
Перегрузка операции индексации [ ] • Операция индексации рассматривается как бинарная операция, где первый операнд – объект класса, а второй операнд – целочисленный индекс. Перегрузка операции индексации позволяет работать с элементами объекта vector как с элементами массива.
• • • • • #include
• • • • • // перегрузка операции = vector: : operator = (vector t) { vector temp; for (int i=0; i<3; i ++) v[i]=t. v[i]; return *this; } // перегрузка операции [] int& vector: : operator[] (int I) { return v[i]; } void vector: : show(void) { for (int i=0; i<3; i ++) cout<
• void main(void) • { • vector v 1(1, 2, 3), v 2(10, 11, 12), v 3; • v 3 = v 1 + v 2; • for (int i=0; i<3; i ++) • cout<





