Читаем Программирование полностью

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


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).

Объекты класса создаются снизу вверх, начиная с объектов базового класса (см. раздел 14.3.1) в порядке их объявления. Затем в порядке объявления создаются члены класса, после чего следует код самого конструктора. Если программист не сделает чего-нибудь очень странного, это гарантирует, что каждый объект класса будет создан до своего использования.

Если конструктор с одним аргументом не объявлен с помощью ключевого слова explicit, то он определяет неявное преобразование типа своего аргумента в свой класс.


class Date {

public:

  Date(string);

  explicit Date(long); // используется целочисленное

                       // представление даты

  // ...

};


void f(Date);


Date d1 = "June 5, 1848"; // OK

f("June 5, 1848");        // OK


Date d2 = 2007*12*31+6*31+5; // ошибка: Date(long) — явный

                             // конструктор

f(2007*12*31+6*31+5);        // ошибка: Date(long) — явный конструктор


Date d3(2007*12*31+6*31+5);        // OK

Date d4 = Date(2007*12*31+6*31+5); // OK

f(Date(2007*12*31+6*31+5));        // OK


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