Форум программистов, компьютерный форум, киберфорум
С++ для начинающих
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск Заказать работу  
 
Рейтинг 4.75/8: Рейтинг темы: голосов - 8, средняя оценка - 4.75
Заблокирован

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

01.12.2011, 00:34. Показов 1781. Ответов 17
Метки нет (Все метки)

Студворк — интернет-сервис помощи студентам
В учебнике (Дейтла, Как программировать на C++, параграф 3.7 стр. 162) сказано следующее:

Класс получает конструктор по умолчанию в двух случаях:
Первый случай вроде понятен

2. Программист явным образом определяет конструктор, не принимающий аргументов. Такой конструктор будет производить инициализацию, специфицированную программистом, и вызовет конструктор по умолчанию для каждого элемента данных, являющегося объектом другого класса.

Тут возникает два следующих вопроса:
1) Следует ли это понимать так, что элемент данных, относящийся к базовому типу, должен инициализироваться явно (если это, конечно нужно), а элемент данных, являющийся классом, инициализируется всегда безусловно и принудительно?
2) Что проиходит в том случае, когда для элемента данных, являющегося класом, не предусмотрено контруктора по умолчанию?
0
Programming
Эксперт
39485 / 9562 / 3019
Регистрация: 12.04.2006
Сообщений: 41,671
Блог
01.12.2011, 00:34
Ответы с готовыми решениями:

Почему, С++ ругается на контруктор?
Почему у меня С++, ругается на контруктор вектора - vec3(const vec3 v) ??? typedef struct vec3 { union { float v; ...

Контруктор шаблонного класса: почему в заданном коде необходим конструктор без параметров?
#include <cstdlib> #include <iostream> #include <dcl.hpp> #include <string> using namespace std; template<typename Type> ...

Создать функцию с двумя аргументами, имеющими значение по умолчанию; вывести на экран значения по умолчанию
Доброго времени суток, помогите пожалуйста с задачей. -Создайте функцию с двумя аргументами, имеющими значение по умолчанию. Выведите...

17
Каратель
Эксперт С++
6610 / 4029 / 401
Регистрация: 26.03.2010
Сообщений: 9,273
Записей в блоге: 1
01.12.2011, 00:52
Цитата Сообщение от thick_int Посмотреть сообщение
1) Следует ли это понимать так, что элемент данных, относящийся к базовому типу, должен инициализироваться явно (если это, конечно нужно), а элемент данных, являющийся классом, инициализируется всегда безусловно и принудительно?
да

Цитата Сообщение от thick_int Посмотреть сообщение
2) Что проиходит в том случае, когда для элемента данных, являющегося класом, не предусмотрено контруктора по умолчанию?
если явная инициализация отсутствует то будет ошибка об отсутствии конструктора по умолчанию
1
Заблокирован
01.12.2011, 00:55
thick_int,
Запутанное изложение, поэтому у меня сразу же возникает отрицательное отношение к этой книге, хотя я ее не читал.

Оставим в стороне эту книгу, и обсудим, что на самом деле имеет место.

Первый важный момент. Конструктор по умочанию - это конструктор, который может быть вызван без аргументов. Это совершенно не означает, тчто конструктор не должен иметь параметров. Это означает, что если он имеет параметры, то все его параметры имеют аргументы по умолчанию.

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

C++
1
MyClass::MyClass( int x = 10, int y = 20 ) {}
явяется конструктором по умолчанию, так как он может быть вызван без аргументов.

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

C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
class A
{
public:
   A( int i ): a( i ) {}
private:
   int a;
};
 
class B
{
 public:
   B( long x, double y ): b1( x ), b2( y ) {}
};
 
class C: public A
{
public:
   C() : A( 10 ), b( B( 20L, 30.0 ) ) {}
private:
   B b;
};
В этом примере класс С имеет конструктор по умолчанию, так как этот конструктор может быть вызван без аргументов. Тем не менее для своего базового класса и для своего подобъекта он вызывает конструкторы, которым должны передаваться аргументы.

Другое дело, если программсит сам не объявил конструктор по умолчанию. В этом случае компилятор сам за него генерирует конструктор по умолчанию, который имеет вид

C++
1
inline MyClass::MyClass() {}
Этот конструктор имеет пустой список инициализации и пустое тело. Поэтому для такого конструктора будут вызваны конструкторы по умолчанию для его базовых классов и для его подобъектов, имеющих тип класса.

И еще я хотел бы добавить, так как вам здесь уже успели сообщить глупость, что в своем конструкторе по умочанию, вы не обязаны явно вызывать конструкторы базовых классов! Они будут вызваны автоматически, если имеются таковые конструкторы по умолчанию для базовых классов!
0
Заблокирован
01.12.2011, 02:00  [ТС]
To Сыроежка:
Вы просто немного не поняли.
Я имел в виду случай, когда элементом данных является класс, то есть речь шла не о наследовании, а о композиции (или агрегировании).

Добавлено через 11 минут
Кстати из этого я так понял, что экземпляр класса, вообще никогда не может находитья в неинициализированном состоянии.
То есть он либо создается и так или иначе инициализируетя, либо вообще не создается
Правильно ли это?
0
Заблокирован
01.12.2011, 02:06
Цитата Сообщение от thick_int Посмотреть сообщение
Я имел в виду случай, когда элементом данных является класс, то есть речь шла не о наследовании, а о композиции (или агрегировании).
1. Если объект данный-член не проинициализируется явно в списке инициализации конструктора хозяина, то он будит сконструирован конструктором по дефолту.

2. Если у него будит отсутствовать конструктор по дефолту, то его придётся инициализировать явно в списках инициализации конструктора-хозяина. Иначе - ошибка компиляции.

Добавлено через 4 минуты
thick_int, вам кстати, Сыроежка толкнул очень подробную речь, которая раскрывает всю эту тему. В том числе - композицию "агрегат - агрегируемый"

Он вам привел иллюстрирующий код, где у агрегируемомго объекта отсуствует конструктор по дефолту.

Ещё раз посмотрите на код Сыроежки. Я его немножко изменил (он теперь не компилируется) , и оставил комментарий.

C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
class A
{
public:
    A( int i ): a( i ) {}
private:
    int a;
};
 
class B
{
    long b1;
    double b2;
public:
    B( long x, double y ): b1( x ), b2( y ) {}
};
 
class C: public A
{
public:
    
    C() : A( 10 ), /*b( B( 20L, 30.0 ) )*/ {} 
    //error C2512: B: нет подходящего конструктора по умолчанию
private:
    B b;
};
0
Заблокирован
01.12.2011, 02:08
Цитата Сообщение от thick_int Посмотреть сообщение
Кстати из этого я так понял, что экземпляр класса, вообще никогда не может находитья в неинициализированном состоянии.
То есть он либо создается и так или иначе инициализируетя, либо вообще не создается
Правильно ли это?
А как вы вообще себе представляете "не инициализируемый экземпляр класса" ?
Если он сконструирован, то в любом случае с помощью какого то конструктора.
А если он не сконструирован, значит его "как бы не существует"
1
Заблокирован
01.12.2011, 02:21  [ТС]
Цитата Сообщение от Сыроежка Посмотреть сообщение
Такое впечатение, что вы не читаете, что вам пишут!
Ну я немного просто ратерялся, таращась на клас B, ищя там объекты класса.
0
Каратель
Эксперт С++
6610 / 4029 / 401
Регистрация: 26.03.2010
Сообщений: 9,273
Записей в блоге: 1
01.12.2011, 02:23
Цитата Сообщение от Bers Посмотреть сообщение
А как вы вообще себе представляете "не инициализируемый экземпляр класса" ?
Если он сконструирован, то в любом случае с помощью какого то конструктора.
А если он не сконструирован, значит его "как бы не существует"
Bers, не путай инициализацию и конструирование
0
Заблокирован
01.12.2011, 02:31
Цитата Сообщение от Jupiter Посмотреть сообщение
Bers, не путай инициализацию и конструирование
Я тебе на будущее советую не удалять комментарии, которые тебе не нравятся. Они не тебе предназначались. И не тебе учить Bers , так как ты вообще даже не понимаешь, запуск конструктора подобъекта класса, который в свою очередь имеет типа класса, есть его инициаизация..

То же мне, умник нашелся, который удаляет сообщения специалистов, а вместо этого всякий бред несет!
0
Заблокирован
01.12.2011, 02:31  [ТС]
Ну и из вего этого можно ли вывестии следующее правило:
Всякий объект, если он не является простым или составным объектом базового типа или функцией или указателем на функцию, должен быть проинициализирован.
При отсутствии соответствующего инициализатора (или схемы инициализации) компилятор генерирует сообщение об ошибке.
Простые или составные объекты базовых типов инициализируются тоже, но мусором.
0
Заблокирован
01.12.2011, 02:37
Цитата Сообщение от thick_int Посмотреть сообщение
Ну и из вего этого можно ли вывестии следующее правило:
Всякий объект, если он не является простым или составным объектом базового типа или функцией или указателем на функцию, должен быть проинициализирован.
При отсутствии соответствующего инициализатора (или схемы инициализации) компилятор генерирует сообщение об ошибке.
Простые или составные объекты базовых типов инициализируются тоже, но мусором.
Все проще. На самом деле, чтобы сконструировать объект, компилятор дожен сконструировать все его подобъекты. Так как подобъекты, имеющие тип класса, могут быть сконструированы только с помощью конструктора своего класса, то очевидно, если конструктор исходного объекта не может вызвать конструктор его подобъекта, то будет сгенерирована ошибка. Вызов конструктора по умолчанию для подобъекта, имеющего тип класса, называется его инициализацией по умолчанию.
0
Заблокирован
01.12.2011, 02:57
thick_int, В этой теме присутствуют как минимум два момента, о которых я сам ни разу ни в одной книге для новичков не видел.

Сам я до этого дошёл лишь на личном опыте, и то - когда обжегся, и несколько часов искал ошибки, силясь понять, что за мистика творится с этим кодом.

Поэтому, обращаю ваше внимание на материал, которого скорее всего нет в вашей книге.

Момент первый: когда начинается тело конструктора хозяина, все данные члены уже построены!

Момент второй: избегай как огня данных-членов, которые зависят друг друга

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

C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
class CSome
{
public:
    //здесь сначала инициализируется а
    //А объект b инициализируется уже построенным объектом а
 
    CSome(int val):a(val), b(a)
    { 
         /*вот здесь все данные-члены уже построены! */
    }
 
private:
    int a;
    int b;
};
 
class CSome1
{
public:
 
    //здесь тоже самое
    CSome1(int val):a(val), b(a){}
 
private:
    //я просто переставил местами 
    //очередность объявления объектов в классе
 
    int b;
    int a;
};
 
 
int main()
{
    
    CSome test(111); //a=111; b=111;
    CSome1 test2(333); //a=333; b=мусор
    return 0;
}
О чем говорит данная иллюстрация?
Сами объекты данные-члены конструируются в том порядке, в каком они объявлены в классе.
В CSome1 объект a не зависит от объекта b, и поэтому он конструируется корректно.
Но в тот момент, когда конструируется объект b, объекта а ещё не существует!!!
Поэтому, объект b конструируется мусором. Хотя в списках инициализации он вроде как на втором месте. Ошибка совершенно не очевидная.
Если не знаешь - можно долго втыкать, и думать: да что не так то?????

Если я не прав - пусть Сыроежка меня поправит.

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

Случай из жизни:
Я тогда только только начал ощущать "вкус жизни, или множественное наследование". И вовсю начал юзать списки инициализации, и вызывать базовые конструкторы классов.
Класс уже являлся частью довольно крупной архитектуры. При том, был полностью проверен.
Потом я сделал несколько модификаций в классе, и решил подправить код класса, что бы он красивее (читабельнее) смотрелся. Ну и по не знанию поменял данные-члены местами.

Никаких предупреждений, никаких ошибок компиляции. Просто иногда программа вела себя не корректно. Вместо нормального отчета выводила в файл такую ахинею....

А потом я несколько часов сидел в отладчике, безуспешно пытаясь понять: что не так?
0
Заблокирован
01.12.2011, 03:05
Bers,

Вообще-то, в хороших книжках пишут, что сначала конструируются базовые классы в том порядке, в котором они перечислены в заголовке класса (за исключением виртуальных классов), а затем конструируются объекты класса в том порядке, в котором они объявлены внутри класса.
Проблема лишь в том, что когда начинающие изучать язык С++ читают эти утверждения, они не заостряют на них внимание, а потому быстро забывают. И вспомниают о них лишь тогда, когда на собственном опыте столкнулись со своим некорректным объявлением класса.
0
 Аватар для SleepMaster
40 / 40 / 7
Регистрация: 26.11.2011
Сообщений: 80
01.12.2011, 03:06
Цитата Сообщение от Bers Посмотреть сообщение
thick_int, В этой теме присутствуют как минимум два момента, о которых я сам ни разу ни в одной книге для новичков не видел.
Цитата Сообщение от Bers Посмотреть сообщение
когда начинается тело конструктора хозяина, все данные члены уже построены!
Ну не скажите. Хорошие книги надо читать, а не для новичков, особенно вам. Я же новичок, а где-то уже вычитал В теле конструктора идёт проверка вводимых данных. Можно написать так:
C++
1
2
3
4
5
6
class A
{
int a;
A(int b):a(b)
        { if (b<0) exit(1); } // тогда объект класса не создается. В остальных случаях - создаётся
}
0
Каратель
Эксперт С++
6610 / 4029 / 401
Регистрация: 26.03.2010
Сообщений: 9,273
Записей в блоге: 1
01.12.2011, 03:13
Цитата Сообщение от Сыроежка Посмотреть сообщение
так как ты вообще даже не понимаешь, запуск конструктора подобъекта класса, который в свою очередь имеет типа класса, есть его инициаизация..
конструирование объекта включает в себя инициализацию, но сказать что конструирование является инициализацией нельзя
0
Заблокирован
01.12.2011, 03:16
Цитата Сообщение от Сыроежка Посмотреть сообщение
затем конструируются объекты класса в том порядке, в котором они объявлены внутри класса.
Порядок инициализации данных-членов стандартизирован?
А то мало ли.. может это на усмотрение компиляторов?
0
Заблокирован
01.12.2011, 03:39
Цитата Сообщение от Jupiter Посмотреть сообщение
конструирование объекта включает в себя инициализацию, но сказать что конструирование является инициализацией нельзя
Я уже написал, что вызов конструктора по умолчанию для объекта, имеющего тип класса, называется инициализацией по умолчанию.

Есть три вида инициализации:
1. Инициализация нулем
2. Инициализация по умолчанию
3. Инициализация значением.

Добавлено через 11 минут
Цитата Сообщение от Bers Посмотреть сообщение
Порядок инициализации данных-членов стандартизирован?
А то мало ли.. может это на усмотрение компиляторов?
Да, стандартиризирован. Иначе бы программисты сталкивались бы с неопределенным поведением. Вы же сами привели пример, к чему приводит нарушение порядка инициализации членов класса.

Добавлено через 5 минут
Цитата Сообщение от Bers Посмотреть сообщение
Порядок инициализации данных-членов стандартизирован?
А то мало ли.. может это на усмотрение компиляторов?
Да, стандартиризирован. Иначе бы программисты сталкивались бы с неопределенным поведением. Вы же сами привели пример, к чему приводит нарушение порядка инициализации членов класса.
1
Заблокирован
01.12.2011, 03:54  [ТС]
Мне почему то кажется, что было бы очень хорошо, если бы вообще такая инициализация
C++
1
CSome(int val):a(val), b(a)
вообще бы была просто недопустимой вне зависимости от порядка, в котором перечислены члены класса.
Иными словами, интуитивно кажется весьма опасным инициализировать одни члены, полагаясь лишь на то, что другие члены уже проинициализированы.
Кажется, что если придерживаться этого правила, тогда и голову не придется ломать над правильным порядком членов класса.
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
inter-admin
Эксперт
29715 / 6470 / 2152
Регистрация: 06.03.2009
Сообщений: 28,500
Блог
01.12.2011, 03:54
Помогаю со студенческими работами здесь

Как сделать значение по умолчанию для параметра, если оно должно быть значением по умолчанию для типа T?
Как сделать значение по умолчанию для параметра, если оно должно быть значением по умолчанию для типа T? Module Program Sub Method(Of...

Значение полей по умолчанию : "нет значения поля по умолчанию"; "Null";"0"
Форумчане, доброго времени суток! Подскажите. пожалуйста, как правильно указывать значение поля по умолчанию в таблице Аксесс 2003?? ...

Значение по умолчанию: "0"; "Null"; "нет значения по умолчанию"
Форумчане, прошу Вашего совета! В свойствах поля таблицы MySQL &quot;Значение по умолчанию&quot; есть : 1.Какое-то значение (Custom) 2....

БД по умолчанию
Добрый день. Изначально было одна БД с названием &quot;orcl_first&quot;. После этого решил сделать вторую БД &quot;oracle_second&quot;. Oracle...

Масштаб по умолчанию
Доброго времени суток, имеется следующий беспорядок - див с фиксированными размерами в который выводится изображение-чертеж &lt;div...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
18
Ответ Создать тему
Новые блоги и статьи
SDL3 для Desktop (MinGW): Рисуем цветные прямоугольники с помощью рисовальщика SDL3 на Си и C++
8Observer8 17.03.2026
Содержание блога Финальные проекты на Си и на C++: finish-rectangles-sdl3-c. zip finish-rectangles-sdl3-cpp. zip
Символические и жёсткие ссылки в Linux.
algri14 15.03.2026
Существует два типа ссылок — символические и жёсткие. Ссылка в Linux — это запись в каталоге, которая может указывать либо на inode «файла-ИСТОЧНИКА», тогда это будет «жёсткая ссылка» (hard link),. . .
[Owen Logic] Поддержание уровня воды в резервуаре количеством включённых насосов: моделирование и выбор регулятора
ФедосеевПавел 14.03.2026
Поддержание уровня воды в резервуаре количеством включённых насосов: моделирование и выбор регулятора ВВЕДЕНИЕ Выполняя задание на управление насосной группой заполнения резервуара,. . .
делаю науч статью по влиянию грибов на сукцессию
anaschu 13.03.2026
прикрепляю статью
SDL3 для Desktop (MinGW): Создаём пустое окно с нуля для 2D-графики на SDL3, Си и C++
8Observer8 10.03.2026
Содержание блога Финальные проекты на Си и на C++: hello-sdl3-c. zip hello-sdl3-cpp. zip Результат:
Установка CMake и MinGW 13.1 для сборки С и C++ приложений из консоли и из Qt Creator в EXE
8Observer8 10.03.2026
Содержание блога MinGW - это коллекция инструментов для сборки приложений в EXE. CMake - это система сборки приложений. Здесь описаны базовые шаги для старта программирования с помощью CMake и. . .
Как дизайн сайта влияет на конверсию: 7 решений, которые реально повышают заявки
Neotwalker 08.03.2026
Многие до сих пор воспринимают дизайн сайта как “красивую оболочку”. На практике всё иначе: дизайн напрямую влияет на то, оставит человек заявку или уйдёт через несколько секунд. Даже если у вас. . .
Модульная разработка через nuget packages
DevAlt 07.03.2026
Сложившийся в . Net-среде способ разработки чаще всего предполагает монорепозиторий в котором находятся все исходники. При создании нового решения, мы просто добавляем нужные проекты и имеем. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru