C++. Объекты класса как члены данных класса. Примеры




Объекты класса как члены данных класса. Примеры


Содержание


Поиск на других ресурсах:

1. Пример объявления и использования объекта класса, который есть членом-данных другого класса

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

В примере объявляется 2 класса:

  • класс CMyPoint, определяющий точку с координатами x, y;
  • класс CMyLine, определяющий линию содержащую два объекта типа CMyPoint. Эти объекты содержат координаты концов отрезка, из которых состоит линия.

Класс CMyPoint содержит:

  • внутренние члены данных x, y;
  • конструктор по умолчанию CMyPoint();
  • методы чтения внутренних данных класса GetX(), GetY();
  • метод SetXY(), устанавливающий новые значения x, y.

Класс CMyLine содержит:

  • внутренние члены-данных класса типа CMyPoint с именами mp1, mp2. Эти члены-данных есть объектами класса CMyPoint. Они определяют 2 точки, из которых состоит линия;
  • конструктор по умолчанию CMyLine();
  • методы чтения значения объектов mp1, mp2 которые имеют соответственно имена GetPoint1(), GetPoint2();
  • метод SetLine() для установления нового значения координат концов отрезка CMyLine;
  • метод Length(), вычисляющий длину отрезка.





Объявление и реализация методов классов CMyPoint и CMyLine

// объявление класса CMyPoint
class CMyPoint
{
    int x;
    int y;

    public:
    CMyPoint(void); // конструктор по умолчанию

    // методы класса
    int GetX(void)
    {
        return x;
    }

    int GetY(void)
    {
        return y;
    }

    void SetXY(int nx, int ny)
    {
        x = nx; y = ny;
    }
};

// конструктор по умолчанию
CMyPoint::CMyPoint(void)
{
    x = y = 0;
}

// ----------------------------------------------
// объявление и реализация методов класса CMyLine
class CMyLine
{
    CMyPoint mp1;
    CMyPoint mp2;

    public:
    // конструктор по умолчанию
    CMyLine(void);

    // методы доступа
    CMyPoint GetPoint1(void)
    {
        return mp1;
    }

    CMyPoint GetPoint2(void)
    {
        return mp2;
    }

    void SetLine(CMyPoint p1, CMyPoint p2);

    // метод, который возвращает длину линии
    double Length(void);
};

// реализация методов класса CMyLine
CMyLine::CMyLine(void)
{
    mp1.SetXY(0,0);
    mp2.SetXY(1,1);
}

// установить новые значения точек
void CMyLine::SetLine(CMyPoint p1, CMyPoint p2)
{
    int tx, ty;
    tx = p1.GetX();
    ty = p1.GetY();
    mp1.SetXY(tx, ty);
    tx = p2.GetX();
    ty = p2.GetY();
    mp2.SetXY(tx, ty);
}

// метод, возвращающий длину линии
double CMyLine::Length(void)
{
    int x1, y1, x2, y2;
    double len;

    x1 = mp1.GetX();
    y1 = mp1.GetY();
    x2 = mp2.GetX();
    y2 = mp2.GetY();
    len = System::Math::Sqrt((x1-x2)*(x1-x2) + (y1-y2)*(y1-y2));
    return len;
}

Демонстрация использования класса CMyLine

CMyPoint mp1, mp2;
CMyLine ml;
int d;

// вызов методов класса CPoint
// заполнение значений объектов mp1, mp2
mp1.SetXY(5, 8);
d = mp1.GetX(); // d = 5
mp2.SetXY(9, 11);

// вызов методов из CMyLine
ml.SetLine(mp1, mp2); // установить новые значения точек

// вызов метода, возвращающего первую точку из линии
mp1 = ml.GetPoint2();

// проверка
d = mp1.GetX(); // d = 9
d = mp1.GetY(); // d = 11

// вычисления длины отрезка ml
// вызов метода Length
double length;
length = ml.Length(); // length = 5.0

2. Каким образом выполняется вызов конструкторов, если в классе A используется объект класса B? Каким образом выделяется память для объектов этих классов?

Если в классе A объявляется объект класса B, то при объявлении объекта класса A конструкторы обоих классов вызываются в следующей последовательности:

  • конструктор класса B;
  • конструктор класса A.

Такую последовательность действий компилятор формирует автоматически.

Память для членов-данных класса, которые есть объектами класса, выделяется при выделении памяти для объекта класса, в котором эти объекты реализованы. То есть, если описать объект класса A, в котором есть объект класса B, то память для объекта класса A выделяется с учетом (включает в себя) памяти объекта класса B.

Например. Если взять класс CMyPoint, который объявлен в п. 1 этой темы, то при создании объекта класса CMyLine, сначала вызывается соответствующий конструктор класса CMyPoint (выделяется память), а затем вызывается конструктор класса CMyLine.

3. Инициализация внутреннего объекта класса с помощью конструктора. Пример

Синтаксис языка C++ позволяет проводить удобную инициализацию внутреннего объекта класса в конструкторе с использованием символа : (двоеточие) и вызова конструктора внутреннего класса.

Например, если в некотором классе OuterClass объявляется экземпляр obj другого класса InnerClass

class OuterClass
{
  ...

  // Внутренний экземпляр класса InnerClass
  InnerClass obj;

  ...
}

то конструктор класса OuterClass может инициализировать этот объект по следующему вызову

class OuterClass
{
  ...

  // Внутренний экземпляр класса InnerClass 
  InnerClass obj;

  // Конструктор класса OuterClass.
  // Этот конструктор получает параметром экземпляр _obj класса InnerClass.
  // В конструкторе происходит инициализация внутреннего объекта obj
  // путем вызова obj(_obj).
  OuterClass(InnerClass _obj) : obj(_obj)
  {
    ...
  }

  ...
}

Пример.

В примере демонстрируются особенности инициализации внутренних объектов типа Point, объявляемых в классе Line, а именно:

  • инициализация внутреннего объекта в конструкторе;
  • делегирование полномочий другому конструктору.

Текст демонстрационного примера следующий:

#include <iostream>
using namespace std;

// Класс, описывающий точку на координатной плоскости
class Point
{
private:
  int x, y; // внутренние поля класса

public:
  // Конструктор без параметров
  Point() :Point(0, 0) // делегирование конструктору с двумя параметрами
  { }

  // Конструктор с двумя параметрами
  Point(int x, int y)
  {
    this->x = x;
    this->y = y;
  }

  // Методы доступа
  int GetX() { return x; }
  int GetY() { return y; }

  void SetXY(int _x, int _y)
  {
    x = _x;
    y = _y;
  }

  // Расстояние от точки до начала координат
  double Length()
  {
    return sqrt(x * x + y * y);
  }
};

// Класс, реализующий линию
class Line
{
private: 
  // В классе Line два внутренних объекта класса Point,
  // которые определяю крайние точки линии.
  Point pt1;
  Point pt2;

public:
  // Конструктор без параметров
  Line() : Line(pt1, pt2) // Делегирование полномочий конструктору с 2 параметрами
  { }

  // Инициализация внутреннего объекта через конструктор
  Line(Point _pt1, Point _pt2) : pt1(_pt1), pt2(_pt2)
  { }

  // Методы доступа к внутренним объектам
  Point GetP1() { return pt1; }
  Point GetP2() { return pt2; }
  void Set(Point _pt1, Point _pt2)
  {
    pt1 = _pt1;
    pt2 = _pt2;
  }

  // Метод, который определяет длину линии
  double Length()
  {
    int x1, y1, x2, y2;
    x1 = pt1.GetX();
    y1 = pt1.GetY();
    x2 = pt2.GetX();
    y2 = pt2.GetY();
    return sqrt((x1 - x2) * (x1 - x2) + (y1 - y2) * (y1 - y2));
  }
};


void main()
{
  // Инициализация объектов в классах 
  Point pt1(1, 1);
  Point pt2(3, 4);

  // Вызов конструктора с 2 параметрами класса Line
  Line ln1(pt1, pt2);

  // Вывести расстояние между точками pt1, pt2
  cout << "(1,1) - (3,4) => " << ln1.Length() << endl;
}

Результат выполнения программы

(1,1) - (3,4) => 3.60555


Связанные темы