Функции-друзья класса

Содержание

Слайд 2

Интерфейс класса Есть два вида определяющих операций класса, задающих его интерфейс:

Интерфейс класса

Есть два вида определяющих операций класса, задающих его интерфейс:
функции-члены класса

(методы)
функции-друзья класса
И те и другие имеют доступ к закрытой части класса
И те и другие должны быть объявлены в структуре класса
Слайд 3

Ключевое слово friend Объявляются в одном или нескольких классах Всегда открыты,

Ключевое слово friend
Объявляются в одном или нескольких классах
Всегда открыты, т.к. это

обычные функции
Имеют полный доступ к свойствам этих классов
Нет вызывающего объекта
Не могут использовать this

Сравнение друзей и методов

Часть одного класса
Могут быть public, private или protected
Имеют полный доступ к свойствам объектов своего класса
Вызываются через вызывающий объект
Используют this для указания вызывающего объекта

функции-члены

функции-друзья

Слайд 4

Объявление друзей const int max_string_length = 128; class String { public:

Объявление друзей

const int max_string_length = 128;
class String {
public:
void set_to( char*

);
int length( );
int read( ); // чтение из stdin
void print( ); // вывод в stdout
String substring (int start, int len);
// возвращает подстроку не изменяя оригинала
friend String concat ( String* , String* ); // м.б. методом
friend String concat ( String* , char* ); // м.б. методом
friend String concat ( char*, String*); // не м.б. методом
private:
// объект типа String – это последовательность из не более чем
// max_string_length символов, оканчивающаяся символом NULL
char text [ max_string_length+1 ];
};
Слайд 5

Программирование друзей #include “mystring.h” #include // для стандартных строковых функций #include

Программирование друзей

#include “mystring.h”
#include // для стандартных строковых функций
#include
#include

// для exit()
String concat ( String* s1, String* s2 ) {
if( s1->length()+s2->length() > max_string_length ) {
fprintf( stderr, “string too large: \"%s %s\".\n",
s1->text, s2->text );
exit(1);
}
String both;
strcpy( both.text, s1->text );
strcat( both.text, s2->text );
return both;
}
Слайд 6

String concat (String* s1, char* s2 ) { if( s1->length() +

String concat (String* s1, char* s2 ) {
if( s1->length() +

strlen(s2) > max_string_length ) {
fprintf( stderr, “string too large: \"%s %s\".\n", s1->text , s2 );
exit(1);
}
String both;
strcpy( both.text, s1->text ); strcat( both.text, s2 );
return both;
}
String concat ( char* s1, String* s2 ) {
if( strlen(s1) + s2->length() > max_string_length ) {
fprintf( stderr, “string too large: \"%s %s\".\n", s1, s2->text );
exit(1);
}
String both;
strcpy( both.text, s1 ); strcat( both.text, s2->text );
return both;
}
Слайд 7

#include “mystring.h” void main( int, char** ) { String firstname, lastname,

#include “mystring.h”
void main( int, char** ) {
String firstname, lastname, name, output

;
firstname.set_to ( “Bilbo”);
lastname.set_to ( “Baggins”);
name = concat ( &firstname , “ ” );
name = concat ( &name, &lastname );
output = concat ( “Name is: ” , &name );
output.print ( );
}

Вызов друзей

Слайд 8

Друзья нескольких классов При одновременной разработке двух (или более) близких по

Друзья нескольких классов

При одновременной разработке двух (или более) близких по предметной

области классов функции-друзья обеспечивают интерфейс между классами
На практике такая ситуация возникает при создании объектно-ориентированных библиотек классов.
Пример. Библиотека векторно-матричных типов данных
Слайд 9

Умножение матрицы на вектор class Matrix; // опережающее описание типа class

Умножение матрицы на вектор

class Matrix; // опережающее описание типа
class Vector {
public:


friend Vector mult ( Matrix* m , Vector* v );
// …….
private:
float elements [ 3 ];
};
class Matrix {
public:
friend Vector mult ( Matrix* m , Vector* v );
// …….
private:
float elements [ 3 ] [ 3 ];
};
Слайд 10

Умножение матрицы на вектор #include “vec_matr.h” Vector mult( Matrix* m, Vector*

Умножение матрицы на вектор
#include “vec_matr.h”
Vector mult( Matrix* m, Vector* v )

{
Vector r ;
int i, j ;
for( i = 0 ; i < 3 ; i++ ) {
r.elements[i] = 0 ;
for( j = 0 ; j < 3 ; j++ )
r.elements[i] += m->elements[i][j] * v->elements[j] ;
}
return r ;
}
Слайд 11

Члены одного класса – друзья другого class Vector; // опережающее описание

Члены одного класса – друзья другого

class Vector; // опережающее описание типа
class

Matrix {
public:
Vector mult ( Vector* v );
// …….
private:
float elements [ 3 ] [ 3 ];
};
class Vector {
public:
friend Vector Matrix::mult ( Vector* v );
// …….
private:
float elements [ 3 ];
};
Слайд 12

Умножение матрицы на вектор #include “vec_mat2.h” Vector Matrix::mult( Vector* v )

Умножение матрицы на вектор
#include “vec_mat2.h”
Vector Matrix::mult( Vector* v ) {
Vector r

;
int i, j ;
for( i = 0 ; i < 3 ; i++ ) {
r.elements[i] = 0 ;
for( j = 0 ; j < 3 ; j++ )
r.elements[i] += this->elements[i][j] * v->elements[j] ;
}
return r ;
}
Слайд 13

«Дружба» классов class Vector; // опережающее описание типа class Matrix {

«Дружба» классов

class Vector; // опережающее описание типа
class Matrix {
public:
Vector mult

( Vector* v );
// …….
private:
float elements [ 3 ] [ 3 ];
};
class Vector {
public:
friend class Matrix;
// …….
private:
float elements [ 3 ];
};
Слайд 14

Дружбы можно избежать при достаточном развитии интерфейса класса class Vector {

Дружбы можно избежать при достаточном развитии интерфейса класса

class Vector {
public:
void

set_elem( int , float );
float elem( int );
// …….
private:
float elements [ 3 ];
};
class Matrix {
public:
void set_elem( int , int , float );
float elem( int , int );
// …….
private:
float elements [ 3 ] [ 3 ];
};
Vector mult( Matrix* m , Vector* v ) ;
Слайд 15

Методы void Matrix::set_elem( int i, int j, float val ) {

Методы


void Matrix::set_elem( int i, int j, float val )
{ elements[i][j] = val

; }
float Matrix :: elem( int i , int j )
{ return elements[i][j] ; }
void Vector :: set_elem( int i, float val )
{ elements[i] = val ; }
float Vector :: elem( int i )
{ return elements[i] ; }
Слайд 16

Умножение матрицы на вектор #include “vec_mat3.h” Vector mult( Matrix* m ,

Умножение матрицы на вектор
#include “vec_mat3.h”
Vector mult( Matrix* m , Vector* v

) {
Vector r ;
int i, j ;
for( i = 0 ; i < 3 ; i++ ) {
r.set_elem( i , 0 ) ;
for( j = 0 ; j < 3 ; j++ )
r.set_elem( i , r.elem(i) + m.elem(i,j) * v->elem(j) ) ;
}
return r ;
}
Слайд 17

inline-функции Общее с макросами код не вызывается, а подставляется определяются в

inline-функции

Общее с макросами
код не вызывается, а подставляется
определяются в h-файлах, а не

в cpp-файлах
их использование экономит время работы программы
возможно увеличение объема программы
при изменении требуется перекомпиляция
Общее с функциями
Принимают параметры, как обычные функции
Выполняется проверка соответствия типов
Можно перегружать
Могут быть членами класса
Особая роль при программировании классов
Слайд 18

Методы, подставляемые inline class Matrix { private: float elements [ 3

Методы, подставляемые inline

class Matrix {
private:
float elements [ 3 ] [

3 ];
public:
void set_elem( int i, int j, float val ) { elements[i][j] = val ; }
float elem(int i, int j ) { return elements[i][j] ; }
};

Приходится первым размещать раздел private
Открывает код методов пользователю
Возрастает объем описания класса

Слайд 19

Методы, подставляемые inline class Matrix { public: void set_elem( int ,

Методы, подставляемые inline

class Matrix {
public:
void set_elem( int , int

, float ) ;
float elem(int , int ) ;
private:
float elements [ 3 ] [ 3 ];
};
inline void Martix::set_elem( int i, int j, float val )
{ elements[i][j] = val ; }
inline float Matrix::elem(int i, int j )
{ return elements[i][j] ; }
Слайд 20

РЕЗЮМЕ Функции-друзья – это обычные функции Развитый интерфейс класса позволяет обойтись

РЕЗЮМЕ

Функции-друзья – это обычные функции
Развитый интерфейс класса позволяет обойтись без функций-друзей
Функции-друзья

приходится использовать вместо функций-членов, когда
первый аргумент не объект данного класса
функция должна иметь доступ к закрытой части сразу нескольких классов
Роль inline-подставляемых функций возрастает при программировании классов
Слайд 21

Упражнение Измените в классе String методы is_the_same_as и is_different_from, сделав их

Упражнение

Измените в классе String методы is_the_same_as и is_different_from, сделав их друзьями.

Добавьте все варианты. Прототипы функций имеют вид:
int is_the_same_as( String , String );
int is_different_from( String , String );
int is_the_same_as( String , char* );
int is_different_from( String , char* );
int is_the_same_as( char* , String );
int is_different_from( char* , String );
Протестируйте следующий синтаксис: