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

С++ для начинающих

Войти
Регистрация
Восстановить пароль
 
 
thick_int
Заблокирован
#1

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

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

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

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

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

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

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

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

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

Брайзер по умолчанию - C#
Скажите пожалуйста как средствами .NET открыть браузер по умолчанию! и передовать запросы!!

Выбор ОС по умолчанию - SUSE Linux
Есть такой Это в grub2. Что нужно подправить, что бы по умолчанию грузилась винда? Несколько раз попробовал - винда вообще из списка...

Конструктор по умолчанию - C++
Показывает ошибку : 1 IntelliSense: для класса "tovar" не существует конструктор по умолчанию Подскажите пожалуйста как сделать ...

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

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

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

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

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

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

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

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

Вообще-то, в хороших книжках пишут, что сначала конструируются базовые классы в том порядке, в котором они перечислены в заголовке класса (за исключением виртуальных классов), а затем конструируются объекты класса в том порядке, в котором они объявлены внутри класса.
Проблема лишь в том, что когда начинающие изучать язык С++ читают эти утверждения, они не заостряют на них внимание, а потому быстро забывают. И вспомниают о них лишь тогда, когда на собственном опыте столкнулись со своим некорректным объявлением класса.
0
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); } // тогда объект класса не создается. В остальных случаях - создаётся
}
0
Jupiter
Каратель
Эксперт С++
6559 / 3980 / 227
Регистрация: 26.03.2010
Сообщений: 9,273
Записей в блоге: 1
Завершенные тесты: 2
01.12.2011, 03:13 #15
Цитата Сообщение от Сыроежка Посмотреть сообщение
так как ты вообще даже не понимаешь, запуск конструктора подобъекта класса, который в свою очередь имеет типа класса, есть его инициаизация..
конструирование объекта включает в себя инициализацию, но сказать что конструирование является инициализацией нельзя
0
01.12.2011, 03:13
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
01.12.2011, 03:13
Привет! Вот еще темы с ответами:

Значение по умолчанию - MS Access
Подскажите, плз., как установить в поле дату по умолчанию 1 января текущего года(любого), в этом году 01.01.2014, в следующем должно быть...

Принтер по умолчанию - Windows XP
Доброго времени суток! Возникла проблема следующего характера: Перед печатью документа (из любого приложения, будь то ms office или...

Значение по умолчанию - C#
Работал с дженериками и интерфейсами. Проблема: есть некоторый интерфейс (INumber), все его элементы поддерживают в той или иной мере...

Проги по умолчанию - Windows 7
Приветствую всех. С наступившим. Недавно установил W7 (наверное 32). Не лиц. Но всё в норме, кроме того, что некоторые файлы не хочет...


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

Или воспользуйтесь поиском по форуму:
15
Ответ Создать тему
Опции темы

КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2017, vBulletin Solutions, Inc.
Рейтинг@Mail.ru