Конструктор (объектно-ориентированное программирование)

Поделись знанием:
Перейти к: навигация, поиск

В объектно-ориентированном программировании конструктор класса (от англ. constructor) — специальный блок инструкций, вызываемый при создании объекта.





Назначение конструктора

Одна из ключевых особенностей ООП — инкапсуляция: внутренние поля объекта напрямую недоступны, и пользователь может работать с объектом только как с единым целым, через открытые (public) методы. Каждый метод, в идеале, должен быть устроен так, чтобы объект, находящийся в «допустимом» состоянии (то есть когда выполняется инвариант класса), после вызова метода также оказался в допустимом состоянии. И первая задача конструктора — перевести поля объекта в такое состояние.

Вторая задача — упростить пользование объектом. Объект — не «вещь в себе», ему часто приходится требовать какую-то информацию от других объектов: например, объект File, создаваясь, должен получить имя файла. Это можно сделать и через метод:

  File file;
  file.open("in.txt", File::omRead);

Но удобнее открытие файла сделать в конструкторе:[1]

  File file("in.txt", File::omRead);

Виды конструкторов

Разнообразные языки программирования представляют несколько разновидностей конструкторов:

  • конструктор с параметрами;
  • конструктор по умолчанию, не принимающий аргументов;
  • именованный конструктор — функция, предполагающая явный вызов по имени, работающая как конструктор
  • конструктор копирования — конструктор, принимающий в качестве аргумента объект того же класса (или ссылку из него);
  • конструктор преобразования — конструктор, принимающий один аргумент (эти конструкторы могут вызываться автоматически для преобразования значений других типов в объекты данного класса).
  • конструктор перемещения (специфично для C++11)
class Complex
{
 public:
  // Конструктор по умолчанию 
  // (в данном случае является также и конструктором преобразования)
  Complex(double i_re = 0, double i_im = 0)
      : re(i_re), im(i_im)
  {}

  // Конструктор копирования
  Complex(const Complex &obj)
  {
   re = obj.re;
   im = obj.im;
  }
  private:
    double re, im;
};

Конструктор с параметрами

Конструкторы, принимающие один или более аргументов, называются параметризованными. Например:

class Example
{
     int x, y;
   public:
     Example();
     Example(int a, int b); // параметризованный конструктор 
};
Example :: Example()
{
}
Example :: Example(int a, int b)
{
     x = a;
     y = b;
}

Параметризованный конструктор может быть вызван явно или неявно, например:

    Example e = Example(0, 50); // явный вызов

    Example e(0, 50);           // неявный вызов

Конструктор по умолчанию

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

Именованный конструктор

Конструктор копирования

Конструктор, аргументом которого является ссылка на объект того же класса. Применяется в C++ для передачи объектов в функции по значению.

Конструктор копирования в основном необходим, когда объект имеет указатели на объекты, выделенные в куче. Если программист не создаёт конструктор копирования, то компилятор создаст неявный конструктор копирования, который копирует указатели как есть, то есть фактическое копирование данных не происходит и два объекта ссылаются на одни и те же данные в куче. Соответственно попытка изменения «копии» повредит оригинал, а вызов деструктора для одного из этих объектов при последующем использовании другого приведёт к обращению в область памяти, уже не принадлежащую программе.

Аргумент должен передаваться именно по ссылке, а не по значению. Это вытекает из коллизии: при передаче объекта по значению (в частности, для вызова конструктора) требуется скопировать объект. Но для того, чтобы скопировать объект, необходимо вызвать конструктор копирования.

Конструктор преобразования

Конструктор, принимающий один аргумент. Задаёт преобразование типа своего аргумента в тип конструктора. Такое преобразование типа неявно применяется только если оно уникально.

Конструктор перемещения

В C++11 появился новый тип неконстантных ссылок, носящий название «ссылка на праводопустимое выражение» (англ. rvalue reference) и обозначаемый как T&&, и новый вид конструкторов — конструкторы перемещения (англ. move constructors). Конструктор перемещения принимает на входе значение неконстантной ссылки на объект класса, и используется для передачи владения ресурсами этого объекта. Конструкторы перемещения были придуманы для решения проблемы потери эффективности, связанной с созданием временных объектов.

Виртуальный конструктор

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

«Виртуальными конструкторами» называют похожий, но другой механизм, присутствующий в некоторых языках — например, он есть в Delphi, но нет в C++ и Java. Этот механизм позволяет создать объект любого заранее неизвестного класса при двух условиях:

  • этот класс является потомком некоего наперёд заданного класса (в данном примере это класс TVehicle);
  • на всём пути наследования от базового класса к создаваемому цепочка переопределения не обрывалась. При переопределении виртуального метода синтаксис Delphi требует ключевое слово overload, чтобы старая и новая функции с разными сигнатурами могли сосуществовать, override для переопределения функции либо reintroduce для задания новой функции с тем же именем — последнее недопустимо.
type
  TVehicle = class
      constructor Create;  virtual;
    end;

  TAutomobile = class (TVehicle)
      constructor Create;  override;
    end;

  TMotorcycle = class (TVehicle)
      constructor Create;  override;
    end;

  TMoped = class (TMotorcycle)  // обрываем цепочку переопределения - заводим новый Create
      constructor Create(x : integer);  reintroduce;
    end;

В языке вводится так называемый классовый тип (метакласс). Этот тип в качестве значения может принимать название любого класса, производного от TVehicle.

type
  CVehicle = class of TVehicle;

Такой механизм позволяет создавать объекты любого заранее неизвестного класса, производного от TVehicle.

var
  cv : CVehicle;
  v : TVehicle;

cv := TAutomobile;
v := cv.Create;

Заметьте, что код

cv := TMoped;
v := cv.Create;

является некорректным — директива reintroduce разорвала цепочку переопределения виртуального метода, и в действительности будет вызван конструктор TMotorcycle.Create (а значит, будет создан мотоцикл, а не мопед!)

См. также Фабрика (шаблон проектирования)

Синтаксис

С++

Имя конструктора должно совпадать с именем класса. Допускается использовать несколько конструкторов с одинаковым именем, но различными параметрами.

Пример

class ClassWithConstructor {
 public:
  /* Инициализация внутреннего объекта с помощью конструктора */
  ClassWithConstructor(float parameter): object(parameter) {}/* вызов конструктора AnotherClass(float); */
 private:
  AnotherClass object;
};

Python

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

Пример

class ClassWithConstructor:

    def __init__(self):
        """This method is constructor."""
        pass

Delphi

В Delphi, в отличие от C++, для объявления конструктора служит ключевое слово constructor. Имя конструктора может быть любым, но рекомендуется называть конструктор Create.

Пример

  TClassWithConstructor = class
    public
    constructor Create;
  end;

Java

Некоторые отличия между конструкторами и другими методами Java:

  • конструкторы не имеют типа возвращаемых данных (на самом деле они всегда возвращают this);
  • конструкторы не могут напрямую вызываться (необходимо использовать ключевое слово new);
  • конструкторы не могут иметь модификаторы synchronized, final, abstract, native и static;

Пример

public class Example {
  private int data;

  // Конструктор по умолчанию
  public Example() {
    this(1);
  }

  // Перегрузка конструктора
  public Example(int input) {
    data = input;
  }
}
// код, иллюстрирующий создание объекта описанным выше конструктором
Example e = new Example(42);

JavaScript

В JavaScript в качестве конструктора выступает обычная функция, используемая в качестве операнда оператора new. Для обращения к созданному объекту используется ключевое слово this.

Пример

function Example(initValue) {
    this.myValue = initValue;
}

Example.prototype.getMyValue = function() {
    return this.myValue; 
}
// код, иллюстрирующий создание объекта описанным выше конструктором
var exampleObject = new Example(120);

Visual Basic .NET

Конструкторы в Visual Basic .NET используют обычный метод объявления с именем New.

Пример

Class Foobar
  Private strData As String
  
  ' Constructor
  Public Sub New(ByVal someParam As String)
     strData = someParam
  End Sub
End Class
' некий код
' иллюстрирующий создание объекта описанным выше конструктором
Dim foo As New Foobar(".NET")

C#

Пример

class myClass
{
  private int mA;
  private string mB;

  public myClass(int a, string b)
  {
    mA = a;
    mB = b;
  }
}
// код, иллюстрирующий создание объекта описанным выше конструктором
myClass c = new myClass(42, "string");

Эйфель

В Эйфеле подпрограммы, которые инициализируют объекты, называются процедурами создания. Процедуры создания в чём-то подобны конструкторам и в чём-то отличаются. Они имеют следующие характеристики:

  • Процедуры создания не имеют никакого явного типа результата возврата (по определению процедуры[Примечание 1]).
  • процедуры создания поименованы (имена ограничены допустимыми идентификаторами);
  • процедуры создания задаются по именам в тексте класса;
  • процедуры создания могут быть вызваны напрямую (как обычные процедуры) для повторной инициализации объектов;
  • каждый эффективный (то есть конкретный, не абстрактный) класс должен (явно или неявно) указать по крайней мере одну процедуру создания;
  • процедуры создания отвечают за приведение только что проинициализированного объекта в состояние, которое удовлетворяет инварианту класса[Примечание 2].

Хотя создание объекта является предметом некоторых тонкостей [Примечание 3], создание атрибута с типовым объявлением x: T, выраженном в виде инструкции создания create x.make состоит из следующей последовательности шагов:

  • создать новый непосредственный экземпляр типа T[Примечание 4];
  • выполнить процедуру создания make для вновь созданного экземпляра;
  • прикрепить вновь созданный объект к сущности x.

Пример

В первом отрывке ниже определяется класс POINT. Процедура make кодируется после ключевого слова feature.

Ключевое слово create вводит список процедур, которые могут быть использованы для инициализации экземпляров класса. В данном случае список содержит default_create, процедуру с пустой реализацией, унаследованной из класса ANY, и процедуру make с реализацией в самом классе POINT.

class
    POINT
create
    default_create, make

feature

    make (a_x_value: REAL; a_y_value: REAL)
        do
            x := a_x_value
            y := a_y_value
        end

    x: REAL
            -- Координата X

    y: REAL
            -- Координата Y
        ...

Во втором отрывке класс, являющийся клиентом класса POINT, имеет объявления my_point_1 и my_point_2 типа POINT.

В коде подпрограммы my_point_1 создаётся с координатами (0.0; 0.0). Поскольку в инструкции создания не указана процедура создания, используется процедура default_create, унаследованная из класса ANY. Эта же строка могла бы быть переписана как create my_point_1.default_create. Только процедуры, указанные как процедуры создания могут использоваться в инструкциях создания (то есть в инструкциях с ключевым словом create).

Следующей идёт инструкция создания для my_point_2, задающая начальные значения для координат my_point_2.

Третья инструкция осуществляет обычный вызов процедуры make для ре-инициализации экземпляра, прикреплянного к my_point_2, другими значениями.

    my_point_1: POINT
    my_point_2: POINT
        ...

            create my_point_1
            create my_point_2.make (3.0, 4.0)
            my_point_2.make (5.0, 8.0)
        ...

ColdFusion

Пример

Необходимо отметить, что в ColdFusion не существует метода-конструктора. Широкое распространение среди сообщества программистов на ColdFusion получил способ вызова метода 'init', выступающего в качестве псевдоконструктора.

<cfcomponent displayname="Cheese">
   <!--- свойства --->
   <cfset variables.cheeseName = "" />
   <!--- псевдоконструктор --->
   <cffunction name="init" returntype="Cheese">
      <cfargument name="cheeseName" type="string" required="true" />
      <cfset variables.cheeseName = arguments.cheeseName />
      <cfreturn this />
   </cffunction>
</cfcomponent>

PHP

Пример

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

class Person
{
   private $name;

   function __construct($name)
   {
       $this->name = $name;
   }
 
   function getName()
   {
       return $this->name;
   }
}

Тем не менее, конструктор в PHP версии 4 (и ранее) — метод класса с именем этого же класса.

class Person
{
   private $name;

   function Person($name)
   {
       $this->name = $name;
   }
 
   function getName()
   {
       return $this->name;
   }
}

Perl

Пример

В Perl конструктор должен применить функцию bless к некой переменной (обычно ссылке на хеш):

package Example;

sub new {
  my $class = shift;
  my $self  = {};
  return bless $self, $class;
}

1;

Но это минимальный базовый вариант, есть множество более продвинутых способов, начиная от use fields и заканчивая Moose.

Упрощенные конструкторы (с псевдокодом)

Конструкторы всегда являются частью реализации классов. Класс (в программировании) описывает спецификации основных характеристик набора объектов, являющихся членами класса, а не отдельные характеристики какого-либо объекта из них. Рассмотрим простую аналогию. Возьмем в качестве примера набор (или класс, используя его более общее значение) учеников некоторой школы. Таким образом мы имеем:

class Student {
    // описание класса учеников
    // ... прочий код ...
}

Тем не менее, класс Student — всего лишь общий шаблон (прототип) наших школьников. Для его использования программист создает каждого школьника в виде объекта или сущности (реализации) класса. Этот объект является тем реальным фрагментом данных в памяти, чьи размер, шаблон, характеристики и (в некоторой мере) поведение определяются описанием класса. Обычный способ создания объектов — вызов конструктора (классы в общем случае могут иметь отдельные конструкторы). Например,

class Student {
    Student (String studentName, String Address, int ID) {
        // ... здесь храним вводимые данные и прочие внутрнние поля ...
    }
    // ...
}

См. также

Напишите отзыв о статье "Конструктор (объектно-ориентированное программирование)"

Примечания

  1. Подпрограммы Эйфеля являются либо процедурами либо функциями. У процедур нет никакого возвращаемого типа. Функции всегда имеют возвращаемый тип.
  2. Поскольку должен быть также удовлетворён инвариант наследуемого(-х) класса(-ов), нет обязательного требования вызова родительских конструкторов.
  3. Полная спецификация содержится в стандартах ISO/ECMA по языку программироная Эйфель в онлайн доступе.[2]
  4. Стандарт Эйфеля требует, чтобы поля были инициализированы при первом доступе к ним, т.ч. нет необходимости осуществлять их инициализацию значениями по умолчанию во время создания объекта.

Ссылки

  1. Конечно, это приводит к определённым техническим трудностям — например, что будет, если из конструктора выпадет исключение? Впрочем, разработчик класса просто должен выполнять требования языка, а в большинстве программ не требуется детальная диагностика и автоматические повторы при ошибках.
  2. [www.ecma-international.org/publications/standards/Ecma-367.htm ISO/ECMA документ описания Эйфеля]
  • [www.cyberforum.ru/blogs/18334/blog103.html Конструкторы и деструкторы]


К:Википедия:Статьи без источников (тип: не указан)

Отрывок, характеризующий Конструктор (объектно-ориентированное программирование)

Крайний кавалергард, огромный ростом рябой мужчина, злобно нахмурился, увидав перед собой Ростова, с которым он неминуемо должен был столкнуться. Этот кавалергард непременно сбил бы с ног Ростова с его Бедуином (Ростов сам себе казался таким маленьким и слабеньким в сравнении с этими громадными людьми и лошадьми), ежели бы он не догадался взмахнуть нагайкой в глаза кавалергардовой лошади. Вороная, тяжелая, пятивершковая лошадь шарахнулась, приложив уши; но рябой кавалергард всадил ей с размаху в бока огромные шпоры, и лошадь, взмахнув хвостом и вытянув шею, понеслась еще быстрее. Едва кавалергарды миновали Ростова, как он услыхал их крик: «Ура!» и оглянувшись увидал, что передние ряды их смешивались с чужими, вероятно французскими, кавалеристами в красных эполетах. Дальше нельзя было ничего видеть, потому что тотчас же после этого откуда то стали стрелять пушки, и всё застлалось дымом.
В ту минуту как кавалергарды, миновав его, скрылись в дыму, Ростов колебался, скакать ли ему за ними или ехать туда, куда ему нужно было. Это была та блестящая атака кавалергардов, которой удивлялись сами французы. Ростову страшно было слышать потом, что из всей этой массы огромных красавцев людей, из всех этих блестящих, на тысячных лошадях, богачей юношей, офицеров и юнкеров, проскакавших мимо его, после атаки осталось только осьмнадцать человек.
«Что мне завидовать, мое не уйдет, и я сейчас, может быть, увижу государя!» подумал Ростов и поскакал дальше.
Поровнявшись с гвардейской пехотой, он заметил, что чрез нее и около нее летали ядры, не столько потому, что он слышал звук ядер, сколько потому, что на лицах солдат он увидал беспокойство и на лицах офицеров – неестественную, воинственную торжественность.
Проезжая позади одной из линий пехотных гвардейских полков, он услыхал голос, назвавший его по имени.
– Ростов!
– Что? – откликнулся он, не узнавая Бориса.
– Каково? в первую линию попали! Наш полк в атаку ходил! – сказал Борис, улыбаясь той счастливой улыбкой, которая бывает у молодых людей, в первый раз побывавших в огне.
Ростов остановился.
– Вот как! – сказал он. – Ну что?
– Отбили! – оживленно сказал Борис, сделавшийся болтливым. – Ты можешь себе представить?
И Борис стал рассказывать, каким образом гвардия, ставши на место и увидав перед собой войска, приняла их за австрийцев и вдруг по ядрам, пущенным из этих войск, узнала, что она в первой линии, и неожиданно должна была вступить в дело. Ростов, не дослушав Бориса, тронул свою лошадь.
– Ты куда? – спросил Борис.
– К его величеству с поручением.
– Вот он! – сказал Борис, которому послышалось, что Ростову нужно было его высочество, вместо его величества.
И он указал ему на великого князя, который в ста шагах от них, в каске и в кавалергардском колете, с своими поднятыми плечами и нахмуренными бровями, что то кричал австрийскому белому и бледному офицеру.
– Да ведь это великий князь, а мне к главнокомандующему или к государю, – сказал Ростов и тронул было лошадь.
– Граф, граф! – кричал Берг, такой же оживленный, как и Борис, подбегая с другой стороны, – граф, я в правую руку ранен (говорил он, показывая кисть руки, окровавленную, обвязанную носовым платком) и остался во фронте. Граф, держу шпагу в левой руке: в нашей породе фон Бергов, граф, все были рыцари.
Берг еще что то говорил, но Ростов, не дослушав его, уже поехал дальше.
Проехав гвардию и пустой промежуток, Ростов, для того чтобы не попасть опять в первую линию, как он попал под атаку кавалергардов, поехал по линии резервов, далеко объезжая то место, где слышалась самая жаркая стрельба и канонада. Вдруг впереди себя и позади наших войск, в таком месте, где он никак не мог предполагать неприятеля, он услыхал близкую ружейную стрельбу.
«Что это может быть? – подумал Ростов. – Неприятель в тылу наших войск? Не может быть, – подумал Ростов, и ужас страха за себя и за исход всего сражения вдруг нашел на него. – Что бы это ни было, однако, – подумал он, – теперь уже нечего объезжать. Я должен искать главнокомандующего здесь, и ежели всё погибло, то и мое дело погибнуть со всеми вместе».
Дурное предчувствие, нашедшее вдруг на Ростова, подтверждалось всё более и более, чем дальше он въезжал в занятое толпами разнородных войск пространство, находящееся за деревнею Працом.
– Что такое? Что такое? По ком стреляют? Кто стреляет? – спрашивал Ростов, ровняясь с русскими и австрийскими солдатами, бежавшими перемешанными толпами наперерез его дороги.
– А чорт их знает? Всех побил! Пропадай всё! – отвечали ему по русски, по немецки и по чешски толпы бегущих и непонимавших точно так же, как и он, того, что тут делалось.
– Бей немцев! – кричал один.
– А чорт их дери, – изменников.
– Zum Henker diese Ruesen… [К чорту этих русских…] – что то ворчал немец.
Несколько раненых шли по дороге. Ругательства, крики, стоны сливались в один общий гул. Стрельба затихла и, как потом узнал Ростов, стреляли друг в друга русские и австрийские солдаты.
«Боже мой! что ж это такое? – думал Ростов. – И здесь, где всякую минуту государь может увидать их… Но нет, это, верно, только несколько мерзавцев. Это пройдет, это не то, это не может быть, – думал он. – Только поскорее, поскорее проехать их!»
Мысль о поражении и бегстве не могла притти в голову Ростову. Хотя он и видел французские орудия и войска именно на Праценской горе, на той самой, где ему велено было отыскивать главнокомандующего, он не мог и не хотел верить этому.


Около деревни Праца Ростову велено было искать Кутузова и государя. Но здесь не только не было их, но не было ни одного начальника, а были разнородные толпы расстроенных войск.
Он погонял уставшую уже лошадь, чтобы скорее проехать эти толпы, но чем дальше он подвигался, тем толпы становились расстроеннее. По большой дороге, на которую он выехал, толпились коляски, экипажи всех сортов, русские и австрийские солдаты, всех родов войск, раненые и нераненые. Всё это гудело и смешанно копошилось под мрачный звук летавших ядер с французских батарей, поставленных на Праценских высотах.
– Где государь? где Кутузов? – спрашивал Ростов у всех, кого мог остановить, и ни от кого не мог получить ответа.
Наконец, ухватив за воротник солдата, он заставил его ответить себе.
– Э! брат! Уж давно все там, вперед удрали! – сказал Ростову солдат, смеясь чему то и вырываясь.
Оставив этого солдата, который, очевидно, был пьян, Ростов остановил лошадь денщика или берейтора важного лица и стал расспрашивать его. Денщик объявил Ростову, что государя с час тому назад провезли во весь дух в карете по этой самой дороге, и что государь опасно ранен.
– Не может быть, – сказал Ростов, – верно, другой кто.
– Сам я видел, – сказал денщик с самоуверенной усмешкой. – Уж мне то пора знать государя: кажется, сколько раз в Петербурге вот так то видал. Бледный, пребледный в карете сидит. Четверню вороных как припустит, батюшки мои, мимо нас прогремел: пора, кажется, и царских лошадей и Илью Иваныча знать; кажется, с другим как с царем Илья кучер не ездит.
Ростов пустил его лошадь и хотел ехать дальше. Шедший мимо раненый офицер обратился к нему.
– Да вам кого нужно? – спросил офицер. – Главнокомандующего? Так убит ядром, в грудь убит при нашем полку.
– Не убит, ранен, – поправил другой офицер.
– Да кто? Кутузов? – спросил Ростов.
– Не Кутузов, а как бишь его, – ну, да всё одно, живых не много осталось. Вон туда ступайте, вон к той деревне, там всё начальство собралось, – сказал этот офицер, указывая на деревню Гостиерадек, и прошел мимо.
Ростов ехал шагом, не зная, зачем и к кому он теперь поедет. Государь ранен, сражение проиграно. Нельзя было не верить этому теперь. Ростов ехал по тому направлению, которое ему указали и по которому виднелись вдалеке башня и церковь. Куда ему было торопиться? Что ему было теперь говорить государю или Кутузову, ежели бы даже они и были живы и не ранены?
– Этой дорогой, ваше благородие, поезжайте, а тут прямо убьют, – закричал ему солдат. – Тут убьют!
– О! что говоришь! сказал другой. – Куда он поедет? Тут ближе.
Ростов задумался и поехал именно по тому направлению, где ему говорили, что убьют.
«Теперь всё равно: уж ежели государь ранен, неужели мне беречь себя?» думал он. Он въехал в то пространство, на котором более всего погибло людей, бегущих с Працена. Французы еще не занимали этого места, а русские, те, которые были живы или ранены, давно оставили его. На поле, как копны на хорошей пашне, лежало человек десять, пятнадцать убитых, раненых на каждой десятине места. Раненые сползались по два, по три вместе, и слышались неприятные, иногда притворные, как казалось Ростову, их крики и стоны. Ростов пустил лошадь рысью, чтобы не видать всех этих страдающих людей, и ему стало страшно. Он боялся не за свою жизнь, а за то мужество, которое ему нужно было и которое, он знал, не выдержит вида этих несчастных.
Французы, переставшие стрелять по этому, усеянному мертвыми и ранеными, полю, потому что уже никого на нем живого не было, увидав едущего по нем адъютанта, навели на него орудие и бросили несколько ядер. Чувство этих свистящих, страшных звуков и окружающие мертвецы слились для Ростова в одно впечатление ужаса и сожаления к себе. Ему вспомнилось последнее письмо матери. «Что бы она почувствовала, – подумал он, – коль бы она видела меня теперь здесь, на этом поле и с направленными на меня орудиями».
В деревне Гостиерадеке были хотя и спутанные, но в большем порядке русские войска, шедшие прочь с поля сражения. Сюда уже не доставали французские ядра, и звуки стрельбы казались далекими. Здесь все уже ясно видели и говорили, что сражение проиграно. К кому ни обращался Ростов, никто не мог сказать ему, ни где был государь, ни где был Кутузов. Одни говорили, что слух о ране государя справедлив, другие говорили, что нет, и объясняли этот ложный распространившийся слух тем, что, действительно, в карете государя проскакал назад с поля сражения бледный и испуганный обер гофмаршал граф Толстой, выехавший с другими в свите императора на поле сражения. Один офицер сказал Ростову, что за деревней, налево, он видел кого то из высшего начальства, и Ростов поехал туда, уже не надеясь найти кого нибудь, но для того только, чтобы перед самим собою очистить свою совесть. Проехав версты три и миновав последние русские войска, около огорода, окопанного канавой, Ростов увидал двух стоявших против канавы всадников. Один, с белым султаном на шляпе, показался почему то знакомым Ростову; другой, незнакомый всадник, на прекрасной рыжей лошади (лошадь эта показалась знакомою Ростову) подъехал к канаве, толкнул лошадь шпорами и, выпустив поводья, легко перепрыгнул через канаву огорода. Только земля осыпалась с насыпи от задних копыт лошади. Круто повернув лошадь, он опять назад перепрыгнул канаву и почтительно обратился к всаднику с белым султаном, очевидно, предлагая ему сделать то же. Всадник, которого фигура показалась знакома Ростову и почему то невольно приковала к себе его внимание, сделал отрицательный жест головой и рукой, и по этому жесту Ростов мгновенно узнал своего оплакиваемого, обожаемого государя.
«Но это не мог быть он, один посреди этого пустого поля», подумал Ростов. В это время Александр повернул голову, и Ростов увидал так живо врезавшиеся в его памяти любимые черты. Государь был бледен, щеки его впали и глаза ввалились; но тем больше прелести, кротости было в его чертах. Ростов был счастлив, убедившись в том, что слух о ране государя был несправедлив. Он был счастлив, что видел его. Он знал, что мог, даже должен был прямо обратиться к нему и передать то, что приказано было ему передать от Долгорукова.
Но как влюбленный юноша дрожит и млеет, не смея сказать того, о чем он мечтает ночи, и испуганно оглядывается, ища помощи или возможности отсрочки и бегства, когда наступила желанная минута, и он стоит наедине с ней, так и Ростов теперь, достигнув того, чего он желал больше всего на свете, не знал, как подступить к государю, и ему представлялись тысячи соображений, почему это было неудобно, неприлично и невозможно.
«Как! Я как будто рад случаю воспользоваться тем, что он один и в унынии. Ему неприятно и тяжело может показаться неизвестное лицо в эту минуту печали; потом, что я могу сказать ему теперь, когда при одном взгляде на него у меня замирает сердце и пересыхает во рту?» Ни одна из тех бесчисленных речей, которые он, обращая к государю, слагал в своем воображении, не приходила ему теперь в голову. Те речи большею частию держались совсем при других условиях, те говорились большею частию в минуту побед и торжеств и преимущественно на смертном одре от полученных ран, в то время как государь благодарил его за геройские поступки, и он, умирая, высказывал ему подтвержденную на деле любовь свою.
«Потом, что же я буду спрашивать государя об его приказаниях на правый фланг, когда уже теперь 4 й час вечера, и сражение проиграно? Нет, решительно я не должен подъезжать к нему. Не должен нарушать его задумчивость. Лучше умереть тысячу раз, чем получить от него дурной взгляд, дурное мнение», решил Ростов и с грустью и с отчаянием в сердце поехал прочь, беспрестанно оглядываясь на всё еще стоявшего в том же положении нерешительности государя.
В то время как Ростов делал эти соображения и печально отъезжал от государя, капитан фон Толь случайно наехал на то же место и, увидав государя, прямо подъехал к нему, предложил ему свои услуги и помог перейти пешком через канаву. Государь, желая отдохнуть и чувствуя себя нездоровым, сел под яблочное дерево, и Толь остановился подле него. Ростов издалека с завистью и раскаянием видел, как фон Толь что то долго и с жаром говорил государю, как государь, видимо, заплакав, закрыл глаза рукой и пожал руку Толю.
«И это я мог бы быть на его месте?» подумал про себя Ростов и, едва удерживая слезы сожаления об участи государя, в совершенном отчаянии поехал дальше, не зная, куда и зачем он теперь едет.
Его отчаяние было тем сильнее, что он чувствовал, что его собственная слабость была причиной его горя.
Он мог бы… не только мог бы, но он должен был подъехать к государю. И это был единственный случай показать государю свою преданность. И он не воспользовался им… «Что я наделал?» подумал он. И он повернул лошадь и поскакал назад к тому месту, где видел императора; но никого уже не было за канавой. Только ехали повозки и экипажи. От одного фурмана Ростов узнал, что Кутузовский штаб находится неподалеку в деревне, куда шли обозы. Ростов поехал за ними.
Впереди его шел берейтор Кутузова, ведя лошадей в попонах. За берейтором ехала повозка, и за повозкой шел старик дворовый, в картузе, полушубке и с кривыми ногами.
– Тит, а Тит! – сказал берейтор.
– Чего? – рассеянно отвечал старик.
– Тит! Ступай молотить.
– Э, дурак, тьфу! – сердито плюнув, сказал старик. Прошло несколько времени молчаливого движения, и повторилась опять та же шутка.
В пятом часу вечера сражение было проиграно на всех пунктах. Более ста орудий находилось уже во власти французов.
Пржебышевский с своим корпусом положил оружие. Другие колонны, растеряв около половины людей, отступали расстроенными, перемешанными толпами.
Остатки войск Ланжерона и Дохтурова, смешавшись, теснились около прудов на плотинах и берегах у деревни Аугеста.
В 6 м часу только у плотины Аугеста еще слышалась жаркая канонада одних французов, выстроивших многочисленные батареи на спуске Праценских высот и бивших по нашим отступающим войскам.