Член-данные класса – объекты другого класса: агрегированные классы. 


Мы поможем в написании ваших работ!



ЗНАЕТЕ ЛИ ВЫ?

Член-данные класса – объекты другого класса: агрегированные классы.



 

Член-данное какого-либо класса может быть переменной, указателем или ссылкой, тип которых – другой известный на данный момент класс. Такой класс называется агрегированным.

Рассмотрим пример.

 

class A

{ int x, y;

  public:

A(int  xx = 0) {x = y = xx;} // конструктор с аргументом по умолчанию

  A(int  xx, int  yy) {x = xx; y = yy;}

void  Print()   {cout << ’\n’ << x << ’ ‘ << y;}

int  Getx()   {return  x;}

int  Gety()   {return  y;}

};

 

class B         // агрегированный класс

{ A a;

 int z;

public:

B() {z = 0;}

    B(int, int, int);

    void  Print();

     …

   };

 

Главное правило при использовании объектов другого класса: конструктор использующего класса отвечает за инициалаизацию член-данных используемых классов!

В нашем примере – это конструктор класса B. И этот конструктор должен быть задан так:

 

B:: B(int, int, int): a(b, c), z(d) { }

                

          список инизиализации

 

Собственные член-данные можно инициализировать и внутри { }:

 

B:: B(int  b, int  c, int  d): a(b, c)  {z = d;}

 

Заметим, что если в классе A есть конструктор по умолчанию, то он будет работать, даже если он явно не указан в списке инициализации конструктора класса B. В нашем примере при работе конструктора B() будет работать конструктор A(int  xx = 0).

Порядок работы конструкторов при объявлении объекта класса B: сначала в A, затем в B.

Несколько сложнее выглядит конструктор агрегированного класса, если член-данное в нем – указатель на объект другого класса, и он определяет массив. В этом случае конструктор должен брать память в динамической области и инициализировать элементы массива. Списком инициализации здесь не обойтись. Рассмотрим на примере, как в этом случае можно определить конструктор агрегированного класса.

Пусть имеется класс Array – числовой массив. Используем его для определения класса числовая матрица Matrix:

 

class Matrix

{Array * a; int   m, n;

public:

Matrix(int   m1, int  n1, int  t = 0); // t!= 0 – создание элементов матрицы случайным образом

Array &operator [ ](int  i)  // возвращает ссылку на i-ую строку матрицы

  {if (i < 0 || i >= m)  {cout << ”Такой строки нет!”); exit(0);}

   return a[i];

  }

void Show();              // вывод матрицы

...

 };

 

 

Matrix:: Matrix(int  m1, int  n1, int  t)

{a = new  Array[m = m1]; // Так как в этом случае используется только конструктор по умолчанию

// класса Array (см п.10), то определить строки длиной n можно таким образом:

n = n1;

for(int  i = 0; i < m; i++)

 {Array b(n, t); // создается массив – строка матрицы, t – инициализация

a[i] = b;       // работает перегруженная операция ‘=’ класса Array

 }

}

 

Пример использования:

 

void main()

{Matrix  c(4, 5, 1);

 c.Show();

 c[1][1] = 100; // Работают две перегруженные операции [ ]: первая – в классе Matrix, вторая – в классе Array

 cout << c[0]; // вывод строки с номером 0 операцией потокового вывода, определенной для класса Array

}

 

Вернемся к классам A и B.

Разберемся, как в классе B можно использовать член-данные х и у из класса A. Определим функцию вывода в классе B:

 

void  B:: Print() {cout << ’\n’ << a.x << ‘ ’ << a.y << ’ ‘ << z;} (1)

 

Так нельзя! a.x, a.y – член-данные из части private класса A

Способы выхода из положения:

1)  использовать a.x и a.y в член-функциях класса B непосредственно станет возможным (см. (1)), если объявить класс B дружественным классу A.

 

class B;

class  A {friend class B;

...

  };

 

2)  использовать x и y через член-функции класса A из части public:

 

void  B:: Print()   {a.Print(); cout << ’ ‘ << z;}

 

3)  в некоторых случаях приходится специально задавать функции, которые возвращают то или иное значение из части private используемого класса. Например, в классе A – функции Getx(), Gety(). Функция Print() в классе B в этом случае может быть определена таким образом

 

void  B:: Print() {cout << ’\n’ << a.Getx() << ’ ‘ << a.Gety() << ’ ‘ << z;}

 

Пример использования агрегированных классов.

 

void  main()

{ A  a1, a2(7, 8);   // работают оба конструктора класса A

B  b1;     // работают конструкторы по умолчанию классов A и B:

            // b1.a.x = b1.a.y = b1.z = 0;

B  b2(1, 2, 3); // работают конструкторы с аргументом сначала A,

// потом B:  b2.a.x = 1; b2.a.y = 2; b2.z = 3;

 a1.Print(); a2.Print();   // функция Print() класса A

 b1.Print(); b2.Print();   // функция Print() класса B

}

 

Рассмотрим графический пример.

Зададим 3 класса: прямоугольник Bar, круг Circ, круг на прямоугольнике CircOnBar.

 

const   int  CF = 7;

class  Bar

{ int   h, w, x, y;

  public:

Bar(int  hh, int  ww, int  xx, int  yy)

      {h = hh; w = ww; x = xx; y = yy;}

void  Show(int  c) { };

};

 

class Circ

{int r, x, y;

public:

Circ(int  rr, int  xx, int  yy)  {r = rr; x = xx; y = yy;}

void Show(int c) { }

};

 

class CircOnBar

{ Bar b;

Circ c;

public:

 CircOnBar(int h, int w, int x, int y, int r): b(h, w, x, y), c(r, x + w / 2, y - r) { }

  void   Show(int  cb, int  cc)

  {b.Show(cb); c.Show(cc);}

  };

 

void  main()

{ int  x = 20, i, dx = 100;

// Определяем массив агрегированных объектов - CircOnBar

 CircOnBar  bc[3] = {CircOnBar(100, 50, x = x + dx, 100, 30),

         CircOnBar(100, 50, x = x + dx, 100, 30),

                            CircOnBar(100, 50, x + dx, 100, 30)};

for(i = 0; i < 3; i++)

bc[i].Show(2 * i + 1, 2 *i + 2);   //Выводим их на экран

CircOnBar * pbc = new  CircOnBar(50, 50, 500, 300, 50); // Объект в динамической памяти:

pbc –> Show(4, 12);

delete  pbc;

}


 



Поделиться:


Последнее изменение этой страницы: 2021-12-07; просмотров: 123; Нарушение авторского права страницы; Мы поможем в написании вашей работы!

infopedia.su Все материалы представленные на сайте исключительно с целью ознакомления читателями и не преследуют коммерческих целей или нарушение авторских прав. Обратная связь - 3.147.238.70 (0.01 с.)