Форум программистов, компьютерный форум CyberForum.ru

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

Восстановить пароль Регистрация
 
thick_int
Заблокирован
01.12.2011, 00:34     Контруктор по умолчанию #1
В учебнике (Дейтла, Как программировать на C++, параграф 3.7 стр. 162) сказано следующее:

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

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

Тут возникает два следующих вопроса:
1) Следует ли это понимать так, что элемент данных, относящийся к базовому типу, должен инициализироваться явно (если это, конечно нужно), а элемент данных, являющийся классом, инициализируется всегда безусловно и принудительно?
2) Что проиходит в том случае, когда для элемента данных, являющегося класом, не предусмотрено контруктора по умолчанию?
Similar
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
01.12.2011, 00:34     Контруктор по умолчанию
Посмотрите здесь:

C++ конструктор по умолчанию
Аргументы по умолчанию C++ C++
Параметры по умолчанию в С. C++
C++ Конструкторы по умолчанию.
C++ Конструктор по умолчанию
После регистрации реклама в сообщениях будет скрыта и будут доступны все возможности форума.
Jupiter
Каратель
Эксперт C++
6543 / 3963 / 226
Регистрация: 26.03.2010
Сообщений: 9,273
Записей в блоге: 1
Завершенные тесты: 2
01.12.2011, 00:52     Контруктор по умолчанию #2
Цитата Сообщение от thick_int Посмотреть сообщение
1) Следует ли это понимать так, что элемент данных, относящийся к базовому типу, должен инициализироваться явно (если это, конечно нужно), а элемент данных, являющийся классом, инициализируется всегда безусловно и принудительно?
да

Цитата Сообщение от thick_int Посмотреть сообщение
2) Что проиходит в том случае, когда для элемента данных, являющегося класом, не предусмотрено контруктора по умолчанию?
если явная инициализация отсутствует то будет ошибка об отсутствии конструктора по умолчанию
Сыроежка
Заблокирован
01.12.2011, 00:55     Контруктор по умолчанию #3
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() {}
Этот конструктор имеет пустой список инициализации и пустое тело. Поэтому для такого конструктора будут вызваны конструкторы по умолчанию для его базовых классов и для его подобъектов, имеющих тип класса.

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

Добавлено через 11 минут
Кстати из этого я так понял, что экземпляр класса, вообще никогда не может находитья в неинициализированном состоянии.
То есть он либо создается и так или иначе инициализируетя, либо вообще не создается
Правильно ли это?
Bers
Заблокирован
01.12.2011, 02:06     Контруктор по умолчанию #5
Цитата Сообщение от 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;
};
Bers
Заблокирован
01.12.2011, 02:08     Контруктор по умолчанию #6
Цитата Сообщение от thick_int Посмотреть сообщение
Кстати из этого я так понял, что экземпляр класса, вообще никогда не может находитья в неинициализированном состоянии.
То есть он либо создается и так или иначе инициализируетя, либо вообще не создается
Правильно ли это?
А как вы вообще себе представляете "не инициализируемый экземпляр класса" ?
Если он сконструирован, то в любом случае с помощью какого то конструктора.
А если он не сконструирован, значит его "как бы не существует"
thick_int
Заблокирован
01.12.2011, 02:21  [ТС]     Контруктор по умолчанию #7
Цитата Сообщение от Сыроежка Посмотреть сообщение
Такое впечатение, что вы не читаете, что вам пишут!
Ну я немного просто ратерялся, таращась на клас B, ищя там объекты класса.
Jupiter
Каратель
Эксперт C++
6543 / 3963 / 226
Регистрация: 26.03.2010
Сообщений: 9,273
Записей в блоге: 1
Завершенные тесты: 2
01.12.2011, 02:23     Контруктор по умолчанию #8
Цитата Сообщение от Bers Посмотреть сообщение
А как вы вообще себе представляете "не инициализируемый экземпляр класса" ?
Если он сконструирован, то в любом случае с помощью какого то конструктора.
А если он не сконструирован, значит его "как бы не существует"
Bers, не путай инициализацию и конструирование
Сыроежка
Заблокирован
01.12.2011, 02:31     Контруктор по умолчанию #9
Цитата Сообщение от Jupiter Посмотреть сообщение
Bers, не путай инициализацию и конструирование
Я тебе на будущее советую не удалять комментарии, которые тебе не нравятся. Они не тебе предназначались. И не тебе учить Bers , так как ты вообще даже не понимаешь, запуск конструктора подобъекта класса, который в свою очередь имеет типа класса, есть его инициаизация..

То же мне, умник нашелся, который удаляет сообщения специалистов, а вместо этого всякий бред несет!
thick_int
Заблокирован
01.12.2011, 02:31  [ТС]     Контруктор по умолчанию #10
Ну и из вего этого можно ли вывестии следующее правило:
Всякий объект, если он не является простым или составным объектом базового типа или функцией или указателем на функцию, должен быть проинициализирован.
При отсутствии соответствующего инициализатора (или схемы инициализации) компилятор генерирует сообщение об ошибке.
Простые или составные объекты базовых типов инициализируются тоже, но мусором.
Сыроежка
Заблокирован
01.12.2011, 02:37     Контруктор по умолчанию #11
Цитата Сообщение от thick_int Посмотреть сообщение
Ну и из вего этого можно ли вывестии следующее правило:
Всякий объект, если он не является простым или составным объектом базового типа или функцией или указателем на функцию, должен быть проинициализирован.
При отсутствии соответствующего инициализатора (или схемы инициализации) компилятор генерирует сообщение об ошибке.
Простые или составные объекты базовых типов инициализируются тоже, но мусором.
Все проще. На самом деле, чтобы сконструировать объект, компилятор дожен сконструировать все его подобъекты. Так как подобъекты, имеющие тип класса, могут быть сконструированы только с помощью конструктора своего класса, то очевидно, если конструктор исходного объекта не может вызвать конструктор его подобъекта, то будет сгенерирована ошибка. Вызов конструктора по умолчанию для подобъекта, имеющего тип класса, называется его инициализацией по умолчанию.
Bers
Заблокирован
01.12.2011, 02:57     Контруктор по умолчанию #12
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 можно запросто. А вот искать причину, почему вроде бы рабочий класс вдруг начал тупить не по деццки будит ой как не просто.

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

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

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

Вообще-то, в хороших книжках пишут, что сначала конструируются базовые классы в том порядке, в котором они перечислены в заголовке класса (за исключением виртуальных классов), а затем конструируются объекты класса в том порядке, в котором они объявлены внутри класса.
Проблема лишь в том, что когда начинающие изучать язык С++ читают эти утверждения, они не заостряют на них внимание, а потому быстро забывают. И вспомниают о них лишь тогда, когда на собственном опыте столкнулись со своим некорректным объявлением класса.
SleepMaster
 Аватар для SleepMaster
40 / 40 / 1
Регистрация: 26.11.2011
Сообщений: 80
01.12.2011, 03:06     Контруктор по умолчанию #14
Цитата Сообщение от 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); } // тогда объект класса не создается. В остальных случаях - создаётся
}
Jupiter
Каратель
Эксперт C++
6543 / 3963 / 226
Регистрация: 26.03.2010
Сообщений: 9,273
Записей в блоге: 1
Завершенные тесты: 2
01.12.2011, 03:13     Контруктор по умолчанию #15
Цитата Сообщение от Сыроежка Посмотреть сообщение
так как ты вообще даже не понимаешь, запуск конструктора подобъекта класса, который в свою очередь имеет типа класса, есть его инициаизация..
конструирование объекта включает в себя инициализацию, но сказать что конструирование является инициализацией нельзя
Bers
Заблокирован
01.12.2011, 03:16     Контруктор по умолчанию #16
Цитата Сообщение от Сыроежка Посмотреть сообщение
затем конструируются объекты класса в том порядке, в котором они объявлены внутри класса.
Порядок инициализации данных-членов стандартизирован?
А то мало ли.. может это на усмотрение компиляторов?
Сыроежка
Заблокирован
01.12.2011, 03:39     Контруктор по умолчанию #17
Цитата Сообщение от Jupiter Посмотреть сообщение
конструирование объекта включает в себя инициализацию, но сказать что конструирование является инициализацией нельзя
Я уже написал, что вызов конструктора по умолчанию для объекта, имеющего тип класса, называется инициализацией по умолчанию.

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

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

Добавлено через 5 минут
Цитата Сообщение от Bers Посмотреть сообщение
Порядок инициализации данных-членов стандартизирован?
А то мало ли.. может это на усмотрение компиляторов?
Да, стандартиризирован. Иначе бы программисты сталкивались бы с неопределенным поведением. Вы же сами привели пример, к чему приводит нарушение порядка инициализации членов класса.
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
01.12.2011, 03:54     Контруктор по умолчанию
Еще ссылки по теме:

C++ Почему, С++ ругается на контруктор?
C++ Конструктор по умолчанию
C++ Конструктор по умолчанию

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

Или воспользуйтесь поиском по форуму:
thick_int
Заблокирован
01.12.2011, 03:54  [ТС]     Контруктор по умолчанию #18
Мне почему то кажется, что было бы очень хорошо, если бы вообще такая инициализация
C++
1
CSome(int val):a(val), b(a)
вообще бы была просто недопустимой вне зависимости от порядка, в котором перечислены члены класса.
Иными словами, интуитивно кажется весьма опасным инициализировать одни члены, полагаясь лишь на то, что другие члены уже проинициализированы.
Кажется, что если придерживаться этого правила, тогда и голову не придется ломать над правильным порядком членов класса.
Yandex
Объявления
01.12.2011, 03:54     Контруктор по умолчанию
Ответ Создать тему
Опции темы

Текущее время: 21:18. Часовой пояс GMT +3.
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2016, vBulletin Solutions, Inc.
Рейтинг@Mail.ru