Главная » Материалы за 13.12.2011
Порядок вызова конструкторов
Категория: C++ энциклопедия » П
Если класс не содержит собственных конструкторов, он инициализируется так, словно компилятор создал конструктор без аргументов за вас. Этот конструктор вызывает конструкторы без аргументов базовых классов и переменных класса. Четко определенный порядок вызова конструкторов не зависит
от того, используются конструкторы стандартные или перегруженные, с аргументами или без:
Описанный порядок применяется рекурсивно, то есть первым конструируется первый базовый класс первого базового класса... и т. д. Он не зависит от порядка, указанного в списке инициализации членов.
Если бы дело обстояло иначе, для разных перегруженных конструкторов мог бы использоваться
разный порядок конструирования. Тогда компилятору было бы трудно гарантировать, что деструкторы
будут вызываться в порядке, обратном порядку вызова конструкторов.
от того, используются конструкторы стандартные или перегруженные, с аргументами или без:
- Сначала вызываются конструкторы базовых классов в порядке их перечисления в списке
наследования (еще один список, в котором после символа : перечисляются базовые классы,
разделенные запятыми). - Затем вызываются конструкторы переменных класса в порядке их объявления в объявлении
класса. - После того как будут сконструированы все базовые классы и переменные, выполняется тело
вашего конструктора.
Описанный порядок применяется рекурсивно, то есть первым конструируется первый базовый класс первого базового класса... и т. д. Он не зависит от порядка, указанного в списке инициализации членов.
Если бы дело обстояло иначе, для разных перегруженных конструкторов мог бы использоваться
разный порядок конструирования. Тогда компилятору было бы трудно гарантировать, что деструкторы
будут вызываться в порядке, обратном порядку вызова конструкторов.
Просмотров: 68
Списки инициализации членов
Категория: C++ энциклопедия » С
Чтобы избавиться от этой проблемы, в C++ находится очередное применение символу : — для создания списков инициализации членов. Так называется список спецификаций конструкторов, разделенных занятыми и расположенных между сигнатурой конструктора и его телом.
В конструкторе Bar список инициализации членов используется для инициализации базового класса Foo. Компилятор выбирает используемый конструктор на основании сигнатуры, определяемой по фактическим аргументам. При отсутствии списка инициализации членов сконструировать Bar было бы невозможно, поскольку компилятор не мог бы определить, какое значение должно передаваться конструктору базового класса Foo. В конструкторе BarBar список инициализации членов использовался для инициализации (то есть вызова конструкторов) переменных f и х. В следующем варианте конструктор работает не столь эффективно (если только компилятор не отличается сверхъестественным интеллектом):
Во втором варианте переменная х сначала инициализируется значением 0 (стандартное требование C++) с использованием по умолчанию конструктора int без аргументов, а затем в теле конструктора ей присваивается значение 17. В первом варианте имеется всего одна инициализация и потому экономится один-два машинных такта. В данном примере это несущественно, поскольку переменная х — целая, но если бы она относилась к более сложному классу с конструктором без аргументов и перегруженным оператором присваивания, то разница была бы вполне ощутима.
Списки инициализации членов нужны там, где у базового класса или переменной нет конструктора без аргументов (точнее, есть один и более конструктор с аргументами, но нет ни одного определенного пользователем конструктора без аргументов). Списки инициализации членов не обязательны в тех
ситуациях, когда все базовые классы и переменные класса либо не имеют конструкторов, либо имеют пользовательский конструктор без аргументов.
class Foo {
public:
Foo(char*);
};
class Bar : public Foo {
public:
Bar(char*);
};
class BarBar {
private:
Foo f;
int x;
public:
BarBar();
};
Bar::Bar(char* s) : Foo(s) {...}
BarBar::BarBar : f(“Hello”), x(17) {...}В конструкторе Bar список инициализации членов используется для инициализации базового класса Foo. Компилятор выбирает используемый конструктор на основании сигнатуры, определяемой по фактическим аргументам. При отсутствии списка инициализации членов сконструировать Bar было бы невозможно, поскольку компилятор не мог бы определить, какое значение должно передаваться конструктору базового класса Foo. В конструкторе BarBar список инициализации членов использовался для инициализации (то есть вызова конструкторов) переменных f и х. В следующем варианте конструктор работает не столь эффективно (если только компилятор не отличается сверхъестественным интеллектом):
BarBar::BarBar() : f(“Hello”)
{
x = 17;
}
Во втором варианте переменная х сначала инициализируется значением 0 (стандартное требование C++) с использованием по умолчанию конструктора int без аргументов, а затем в теле конструктора ей присваивается значение 17. В первом варианте имеется всего одна инициализация и потому экономится один-два машинных такта. В данном примере это несущественно, поскольку переменная х — целая, но если бы она относилась к более сложному классу с конструктором без аргументов и перегруженным оператором присваивания, то разница была бы вполне ощутима.
Списки инициализации членов нужны там, где у базового класса или переменной нет конструктора без аргументов (точнее, есть один и более конструктор с аргументами, но нет ни одного определенного пользователем конструктора без аргументов). Списки инициализации членов не обязательны в тех
ситуациях, когда все базовые классы и переменные класса либо не имеют конструкторов, либо имеют пользовательский конструктор без аргументов.
Просмотров: 90
Конструкторы с аргументами
Категория: C++ энциклопедия » К
Конструкторы, как и все остальные функции, можно перегружать. Вы можете объявить столько сигнатур конструкторов, сколько вам потребуется. Единственное настоящее отличие между сигнатурами конструкторов и обычных функций заключается в том, что конструкторы не имеют возвращаемого значения и не могут объявляться константными. Если вы объявите какие-либо конструкторы с аргументами, но не объявите конструктора без аргументов, то компилятор не позволит конструировать объекты этого класса, даже в качестве базового для другого класса, с использованием конструктора без аргументов.
class Foo {
public:
Foo(char*);
};
Foo f; // Нельзя – нет конструктора без аргументов!
class Bar : public Foo {
public:
Bar();
};
Bar::Bar()
{
// Ошибка! Нет конструктора Foo без аргументов
}Просмотров: 40
Конструкторы без аргументов
Категория: C++ энциклопедия » К
Если в вашем классе имеется конструктор, который вызывается без аргументов, он используется по умолчанию в трех следующих случаях.
Если в списке инициализации членов (см. следующий раздел) конструктора Bar не указан какой-нибудь другой конструктор Foo, то при каждом создании экземпляра Ваг будет вызываться конструктор Foo без аргументов. Аналогично, если f отсутствует в списке инициализации членов
конструктора BarBar, будет использован конструктор Foo без аргументов. Наконец, при каждом создании экземпляра Foo без указания конструктора по умолчанию используется конструктор без аргументов.
class Foo {
public:
Foo();
};
class Bar : public Foo { // 1. Базовый класс
public:
Bar();
};
class BarBar {
private:
Foo f; // 2 . П еременная класса
};
Foo f; // 3 . С озданный экземпляр Foo
Foo* f1 = new Foo; // 3. То же, что и предыдущая строкаЕсли в списке инициализации членов (см. следующий раздел) конструктора Bar не указан какой-нибудь другой конструктор Foo, то при каждом создании экземпляра Ваг будет вызываться конструктор Foo без аргументов. Аналогично, если f отсутствует в списке инициализации членов
конструктора BarBar, будет использован конструктор Foo без аргументов. Наконец, при каждом создании экземпляра Foo без указания конструктора по умолчанию используется конструктор без аргументов.
Просмотров: 32
Конструкторы
Категория: C++ энциклопедия » К
Конструктор можно рассматривать двояко — как функцию, инициализирующую объект, или, с позиций математики, как отображение аргументов конструктора на домен класса. Я предпочитаю второй подход, поскольку он помогает разобраться с некоторыми языковыми средствами (например,
операторами преобразования).
С конструкторами связаны очень сложные правила, но каждый программист C++ должен досконально знать их, иначе минимум три ночи в году ему придется проводить за отладкой.
операторами преобразования).
С конструкторами связаны очень сложные правила, но каждый программист C++ должен досконально знать их, иначе минимум три ночи в году ему придется проводить за отладкой.
Просмотров: 32
