Читаем Программирование. Принципы и практика использования C++ Исправленное издание полностью

  Vector operator*(const Matrix&, const Vector&); // есть доступ

  // ...

};


class Matrix {

  friend

  Vector operator*(const Matrix&, const Vector&); // есть доступ

  // ...

};


Как показано выше, обычно это относится к функциям, которым нужен доступ к двум классам. Другое предназначение ключевого слова friend — обеспечивать функцию доступа, которую нельзя вызывать как функцию-член.


class Iter {

public:

  int distance_to(const iter& a) const;

  friend int difference(const Iter& a, const Iter& b);

  // ...

};


void f(Iter& p, Iter& q)

{

  int x = p.distance_to(q); // вызов функции-члена 

  int y = difference(p,q);  // вызов с помощью математического

                            // синтаксиса

  // ...

}


Отметим, что функцию, объявленную с помощью ключевого слова friend, нельзя объявлять виртуальной.

A.12.2. Определения членов класса

Члены класса, являющиеся целочисленными константами, функциями или типами, могут быть определены как в классе, так и вне его.


struct S {

  static const int c = 1;

  static const int c2;

  void f { }

  void f2;

  struct SS { int a; };

  struct SS2;

};


Члены, которые не были определены в классе, должны быть определены “где-то”.


const int S::c2 = 7;

void S::f2 { }

struct S::SS2 { int m; };


Статические константные целочисленные члены класса (static const int) представляют собой особый случай. Они просто определяют символические целочисленные константы и не находятся в памяти, занимаемой объектом. Нестатические данные-члены не требуют отдельного определения, не могут быть определены отдельно и инициализироваться в классе.


struct X {

  int x;

  int y = 7; // ошибка: нестатические данные-члены

             // не могут инициализироваться внутри класса

  static int z = 7; // ошибка: данные-члены, не являющиеся

                    // константами, не могут инициализироваться

                    // внутри класса

  static const string ae = "7"; // ошибка: нецелочисленный тип

                                // нельзя инициализировать

                                // внутри класса

  static const int oe = 7; // OK: статический константный

                           // целочисленный тип

};


int X::x = 7; // ошибка: нестатические члены класса нельзя

              // определять вне класса 


Если вам необходимо инициализировать не статические и не константные данные-члены, используйте конструкторы.

Функции-члены не занимают память, выделенную для объекта.


struct S {

 int m;

 void f;

};


Здесь sizeof(S)==sizeof(int)

. На самом деле стандартом это условие не регламентировано, но во всех известных реализациях языка оно выполняется. Следует подчеркнуть, что класс с виртуальной функцией имеет один скрытый член, обеспечивающий виртуальные вызовы (см. раздел 14.3.1).

A.12.3. Создание, уничтожение и копирование

Определить смысл инициализации объекта класса можно, определив один или несколько конструкторов (constructors). Конструктор — это функция-член, не имеющая возвращаемого значения, имя которой совпадает с именем класса.


class Date {

public:

  Date(int yy,int mm,int dd):y(yy),m(mm),d(dd) { }

  // ...

private:

  int y,m,d;

};


Date d1(2006,11,15); // OK: инициализация с помощью конструктора

Date d2;             // ошибка: нет инициализации

Date d3(11,15);      // ошибка: неправильная инициализация

                     // (требуются три инициализатора)


Обратите внимание на то, что данные-члены могут быть инициализированы с помощью списка инициализации в конструкторе. Члены класса инициализируются в порядке их определения в классе.

Конструкторы обычно используются для установления инвариантов класса и получения ресурсов (см. разделы 9.4.2 и 9.4.3).

Перейти на страницу:
Нет соединения с сервером, попробуйте зайти чуть позже