C++ для начинающих - страница 14

стр.

На самом деле, нет. С++ имеет механизм встроенных (inline) функций. Текст встроенной функции подставляется компилятором в то место, где записано обращение к ней. (Это напоминает механизм макросов, реализованный во многих языках, в том числе и в С++. Однако есть определенные отличия, о которых мы сейчас говорить не будем.) Вот пример. Если у нас есть следующий фрагмент кода:


>for (int index=0; indexarray.size(); ++index)

>// ...


то функция size() не будет вызываться _size раз во время исполнения. Вместо вызова компилятор подставит ее текст, и результат компиляции предыдущего кода будет в точности таким же, как если бы мы написали:


>for (int index=0; indexarray._size; ++index)

>// ...


Если функция определена внутри тела класса (как в нашем случае), она автоматически считается встроенной. Существует также ключевое слово inline, позволяющее объявить встроенной любую функцию.

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

Одна из самых распространенных ошибок при программировании (на любом языке) состоит в том, что объект используется без предварительной инициализации. Чтобы помочь избежать этой ошибки, С++ обеспечивает механизм автоматической инициализации для определяемых пользователем классов – конструктор класса.

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

Функция-член класса, носящее то же имя, что и сам класс, считается конструктором. (Нет никаких специальных ключевых слов, позволяющих определить конструктор как-то по-другому.) Мы уже сказали, что конструкторов может быть несколько. Как же так: разные функции с одинаковыми именами?

В С++ это возможно. Разные функции могут иметь одно и то же имя, если у этих функций различны количество и/или типы параметров. Это называется перегрузкой функции. Обрабатывая вызов перегруженной функции, компилятор смотрит не только на ее имя, но и на список параметров. По количеству и типам передаваемых параметров компилятор может определить, какую же из одноименных функций нужно вызывать в данном случае. Рассмотрим пример. Мы можем определить следующий набор перегруженных функций min(). (Перегружаться могут как обычные функции, так и функции-члены.)


>// список перегруженных функций min()

>// каждая функция отличается от других списком параметров

>#include string


>int min (const int *pia,int size);

>int min (int, int);

>int min (const char *str);

>char min (string);

>string min (string,string);


Поведение перегруженных функций во время выполнения ничем не отличается от поведения обычных. Компилятор определяет нужную функцию и помещает в объектный код именно ее вызов. (В главе 9 подробно обсуждается механизм перегрузки.)

Итак, вернемся к нашему классу IntArray. Давайте определим для него три конструктора:


>class IntArray {

>public:

>explicit IntArray (int sz = DefaultArraySize);

>IntArray (int *array, int array_size);

>IntArray (const IntArray rhs);

>// ...

>private:

>static const int DefaultArraySize = 12;

>}


Первый из перечисленных конструкторов


>IntArray (int sz = DefaultArraySize);


называется конструктором по умолчанию, потому что он может быть вызван без параметров. (Пока не будем объяснять ключевое слово explicit.) Если при создании объекта ему задается параметр типа int, например


>IntArray array1(1024);


то значение 1024 будет передано в конструктор. Если же размер не задан, допустим:

>IntArray array2;

то в качестве значения отсутствующего параметра конструктор принимает величину DefaultArraySize. (Не будем пока обсуждать использование ключевого слова static в определении члена DefaultArraySize: об этом говорится в разделе 13.5. Скажем лишь, что такой член данных существует в единственном экземпляре и принадлежит одновременно всем объектам данного класса.)

Вот как может выглядеть определение нашего конструктора по умолчанию:


>IntArray::IntArray (int sz)

>{

>// инициализация членов данных

>_size = sz;

>ia = new int[_size];