Форум программистов «Весельчак У»
  *
Добро пожаловать, Гость. Пожалуйста, войдите или зарегистрируйтесь.
Вам не пришло письмо с кодом активации?

  • Рекомендуем проверить настройки временной зоны в вашем профиле (страница "Внешний вид форума", пункт "Часовой пояс:").
  • У нас больше нет рассылок. Если вам приходят письма от наших бывших рассылок mail.ru и subscribe.ru, то знайте, что это не мы рассылаем.
   Начало  
Наши сайты
Помощь Поиск Календарь Почта Войти Регистрация  
 
Страниц: [1]   Вниз
  Печать  
Автор Тема: конструктор  (Прочитано 24890 раз)
0 Пользователей и 1 Гость смотрят эту тему.
Алексей++
глобальный и пушистый
Глобальный модератор

ru
Offline Offline
Сообщений: 13


« : 11-10-2005 07:31 » 

скажите, в чём разница

Код:
CChild::CChild( ) : CParent()
{
//код
}

и

Код:
CChild::CChild( )
{
CParent::CParent();
//код
}

?
Записан

Alf
Гость
« Ответ #1 : 11-10-2005 07:54 » 

В первом случае имеет место инициализация CChild, во втором - нет.
Записан
Алексей++
глобальный и пушистый
Глобальный модератор

ru
Offline Offline
Сообщений: 13


« Ответ #2 : 11-10-2005 08:04 » 

то есть вызов CParent::CParent() - холостой для этого объекта? Или я что-то не понимаю
Записан

Alf
Гость
« Ответ #3 : 11-10-2005 08:08 » 

Нет, не холостой.

Ты представляешь себе,что такое инициализация объекта?
Записан
Алексей++
глобальный и пушистый
Глобальный модератор

ru
Offline Offline
Сообщений: 13


« Ответ #4 : 11-10-2005 08:30 » 

видимо нет Улыбаюсь

гавары, что это Улыбаюсь
Записан

Alf
Гость
« Ответ #5 : 11-10-2005 09:02 » 

Погляди для начала здесь, чтобы не повторяться: https://forum.shelek.ru/index.php/topic,6012.0.html
Записан
Алексей++
глобальный и пушистый
Глобальный модератор

ru
Offline Offline
Сообщений: 13


« Ответ #6 : 11-10-2005 09:51 » 

я всё равно не понял разницу
Записан

nikedeforest
Команда клуба

ru
Offline Offline
Пол: Мужской

« Ответ #7 : 11-10-2005 10:20 » 

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

ещё один вопрос ...
Alf
Гость
« Ответ #8 : 11-10-2005 10:28 » 

Инициализируется объект один раз в момент создания, а присавивать потом можно сколько угодно раз (при условии, что присваивание определено). Я там в обсуждении привел пример, когда только инициализация применима.

Если у тебя все переменные-члены класса простых типов, не объектные, то разница не столь велика. А если объекты, то инициализация и присваивание могут иметь совершенно различный смысл.
Записан
Алексей++
глобальный и пушистый
Глобальный модератор

ru
Offline Offline
Сообщений: 13


« Ответ #9 : 11-10-2005 10:34 » 

ладно, поверим на слово Улыбаюсь
нуна так нуна. Хотя не совсем понятно
Записан

nikedeforest
Команда клуба

ru
Offline Offline
Пол: Мужской

« Ответ #10 : 11-10-2005 10:40 » 

Цитата
а присавивать потом можно сколько угодно раз (при условии, что присваивание определено)
Цитата
Если у тебя все переменные-члены класса простых типов, не объектные, то разница не столь велика. А если объекты, то инициализация и присваивание могут иметь совершенно различный смысл.
Я так понимаю, это к примеру, если мы перегрузили оператор =, то мы не сможем провести обычное присваивание, а при инициализации оно проведется. Я правильно понял? Или я мыслЮ плохо оформил?
Записан

ещё один вопрос ...
Джон
просто
Администратор

de
Offline Offline
Пол: Мужской

« Ответ #11 : 11-10-2005 10:43 » 

Тк в данном конкретном случае в коде нет никаких присваиваний, более того вызываются конструкторы без параметров, то соглашусь с nikedeforest - разницы нет. Просто первая запись более привычна.
Записан

Я вам что? Дурак? По выходным и праздникам на работе работать. По выходным и праздникам я работаю дома.
"Just because the language allows you to do something does not mean that it’s the correct thing to do." Trey Nash
"Physics is like sex: sure, it may give some practical results, but that's not why we do it." Richard P. Feynman
"All science is either physics or stamp collecting." Ernest Rutherford
"Wer will, findet Wege, wer nicht will, findet Gründe."
Джон
просто
Администратор

de
Offline Offline
Пол: Мужской

« Ответ #12 : 11-10-2005 10:48 » 

Разница только в том, что при инициализации СРАЗУ создаётся объект с заданными значениями полей данных. При присваивании - сначала создаётся объект с КАКИМИ-ТО значениями, которые при присваивании переписываются. Обычно проблема может возникнуть если между этими двумя событиями может произойти ещё что-нибудь. Поэтому метод "мгновенной" иницализации предпочтительней.
Записан

Я вам что? Дурак? По выходным и праздникам на работе работать. По выходным и праздникам я работаю дома.
"Just because the language allows you to do something does not mean that it’s the correct thing to do." Trey Nash
"Physics is like sex: sure, it may give some practical results, but that's not why we do it." Richard P. Feynman
"All science is either physics or stamp collecting." Ernest Rutherford
"Wer will, findet Wege, wer nicht will, findet Gründe."
Alf
Гость
« Ответ #13 : 11-10-2005 11:01 » 

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

А вот в общем случае, когда конструктор имеет параметры, разница между инициализацией и присваиванием может быть значительной. Так что решай сам - стоит ли тебе делать исключение для конструктора без параметров и изобретать для него особую нотацию или же инициализировать все объекты явно, как положено при хорошем стиле объектного программирования.
Записан
Алексей++
глобальный и пушистый
Глобальный модератор

ru
Offline Offline
Сообщений: 13


« Ответ #14 : 11-10-2005 11:03 » 

Разница только в том, что при инициализации СРАЗУ создаётся объект с заданными значениями полей данных. При присваивании - сначала создаётся объект с КАКИМИ-ТО значениями

вот теперь я понял Улыбаюсь
Записан

Алексей++
глобальный и пушистый
Глобальный модератор

ru
Offline Offline
Сообщений: 13


« Ответ #15 : 11-10-2005 11:04 » 

> Так что решай сам - стоит ли тебе делать исключение для конструктора
> без параметров

думаю не стОит , убедили Улыбаюсь
Записан

LP
Помогающий

ru
Offline Offline

« Ответ #16 : 12-10-2005 18:41 » 

Цитата
скажите, в чём разница
Разница в том, что второй пример не компилируется, а первый - да Улыбаюсь Но даже если найти компилятор, который будет компилировать второй пример, то разница скорее всего все равно будет, так как в 1-м примере конструктор базового класса вызывался один раз, а во втором он будет вызван 2 раза.

Код:
class CParent {...};

class CChild: public CParent {...};

...

//случай 1
CChild::CChild( )//здесь неявно вызывается конструктор базового класса
{
//код
}

//случай 2
CChild::CChild( ) : CParent()//здесь явно вызывается конструктор базового класса
{
//код
}

//случай 3
CChild::CChild( )//здесь неявно вызывается конструктор базового класса
{
CParent::CParent();//здесь (незаконно) второй раз вызывается конструктор базового класса
//код
}

Допустим, например, в конструкторе базового классе мы динамически выделяем память:
Код:
m_ptr = new int[20];
Если конструктор будет вызван дважды, то адрес первого блока памяти мы безвозвратно потеряем и получим утечку памяти.
« Последнее редактирование: 12-10-2005 19:12 от LP » Записан

Если эта надпись уменьшается, значит ваш монитор уносят
Finch
Спокойный
Администратор

il
Offline Offline
Пол: Мужской
Пролетал мимо


« Ответ #17 : 12-10-2005 19:10 » 

Здесь еше возможен еше один подводный камень. Когда компилятор видит вызов конструктора, то под это дело он выделяет память на переменные класса. Когда так:
Код:
CChild::CChild( ) : CParent()
{
//код
}
То компилятор понимает, что этого не требуется делать.
Записан

Не будите спашяго дракона.
             Джаффар (Коша)
LP
Помогающий

ru
Offline Offline

« Ответ #18 : 12-10-2005 19:20 » 

Finch, я не понял, что ты имеешь в виду?
Записан

Если эта надпись уменьшается, значит ваш монитор уносят
Finch
Спокойный
Администратор

il
Offline Offline
Пол: Мужской
Пролетал мимо


« Ответ #19 : 12-10-2005 19:28 » 

Я как-то сдуру хотел такое сделать, но вызвать другой конструктор своего же класса. И долго ловил глюк. Почему же у меня переменные не иницилизируются, но при этом в дебаге показывается, что все в порядке. Помог ассемблерный дебаг, который показал, что в начале конструктора компилятор ставит автоматом код на выделение памяти под экземпляр класса. И естественно this был разный.
« Последнее редактирование: 12-10-2005 19:34 от Finch » Записан

Не будите спашяго дракона.
             Джаффар (Коша)
Джон
просто
Администратор

de
Offline Offline
Пол: Мужской

« Ответ #20 : 12-10-2005 21:54 » 

Разница в том, что второй пример не компилируется

Великолепно компилирутся и выполняется в VS 6.0 и .NET 2003

Насчёт двойного вызова - абсолютно прав! Как-то про стандартный вызов и позабыли.   Так больше нельзя...
« Последнее редактирование: 12-10-2005 21:56 от Джон » Записан

Я вам что? Дурак? По выходным и праздникам на работе работать. По выходным и праздникам я работаю дома.
"Just because the language allows you to do something does not mean that it’s the correct thing to do." Trey Nash
"Physics is like sex: sure, it may give some practical results, but that's not why we do it." Richard P. Feynman
"All science is either physics or stamp collecting." Ernest Rutherford
"Wer will, findet Wege, wer nicht will, findet Gründe."
LP
Помогающий

ru
Offline Offline

« Ответ #21 : 12-10-2005 22:24 » 

Насчет "не компилируется" я имел в виду - comeau on-line. Как известно это самый соответствующий стандарту С++ компилятор. Поэтому, думаю, вызов конструктора как функции на самом деле запрещен, хотя в стандарте я ничего явно про этот случай не нашел... Разве, что это:
12.1/2
"Because constructors do not have names, they are never found during name lookup"
Записан

Если эта надпись уменьшается, значит ваш монитор уносят
LP
Помогающий

ru
Offline Offline

« Ответ #22 : 06-12-2005 12:53 » new

Лучше поздно, чем никогда.  Жжешь

В этом коде:
Код:
CChild::CChild( )
{
CParent::CParent();
//код
}
CParent::CParent(); означает создание временного объекта, который тут же уничтожается. - Это на MSVC7.1, gcc 3.4.4.

Такая программа
Код:
#include <iostream>

struct CParent
{
CParent()
{
std::cout << "CParent::CParent()" << std::endl;
}
~CParent()
{
std::cout << "~CParent::CParent()" << std::endl;
}
};

struct CChild : CParent
{
CChild()
{
std::cout << "before" << std::endl;
CParent::CParent();
std::cout << "after" << std::endl;
}
};

int main()
{
CChild obj;
return 0;
}
выводит
Код:
CParent::CParent()
before
CParent::CParent()
~CParent::CParent()
after
~CParent::CParent()

Однако Comeau C++ on-line, как я говорил, это не компилирует:
Цитата
"ComeauTest.c", line 20: error: a constructor or destructor may not have its
          address taken
        CParent::CParent();
        ^

Можно написать еще одну статью про ужасы С++.  Улыбаюсь
Записан

Если эта надпись уменьшается, значит ваш монитор уносят
Страниц: [1]   Вверх
  Печать  
 

Powered by SMF 1.1.21 | SMF © 2015, Simple Machines