Алексей++
глобальный и пушистый
Глобальный модератор
Offline
Сообщений: 13
|
|
« : 11-10-2005 07:31 » |
|
скажите, в чём разница CChild::CChild( ) : CParent() { //код }
и CChild::CChild( ) { CParent::CParent(); //код }
?
|
|
|
Записан
|
|
|
|
Alf
Гость
|
|
« Ответ #1 : 11-10-2005 07:54 » |
|
В первом случае имеет место инициализация CChild, во втором - нет.
|
|
|
Записан
|
|
|
|
Алексей++
глобальный и пушистый
Глобальный модератор
Offline
Сообщений: 13
|
|
« Ответ #2 : 11-10-2005 08:04 » |
|
то есть вызов CParent::CParent() - холостой для этого объекта? Или я что-то не понимаю
|
|
|
Записан
|
|
|
|
Alf
Гость
|
|
« Ответ #3 : 11-10-2005 08:08 » |
|
Нет, не холостой.
Ты представляешь себе,что такое инициализация объекта?
|
|
|
Записан
|
|
|
|
Алексей++
глобальный и пушистый
Глобальный модератор
Offline
Сообщений: 13
|
|
« Ответ #4 : 11-10-2005 08:30 » |
|
видимо нет гавары, что это
|
|
|
Записан
|
|
|
|
Alf
Гость
|
|
« Ответ #5 : 11-10-2005 09:02 » |
|
|
|
|
Записан
|
|
|
|
Алексей++
глобальный и пушистый
Глобальный модератор
Offline
Сообщений: 13
|
|
« Ответ #6 : 11-10-2005 09:51 » |
|
я всё равно не понял разницу
|
|
|
Записан
|
|
|
|
nikedeforest
|
|
« Ответ #7 : 11-10-2005 10:20 » |
|
Альф, а правда есть ли разница в данном случае? Одно дело когда мы присваиваем значение переменной или константе, а здесь ведь вызов метода идет. Какая разница где его вызывать, в списке инициализации или в процессе работы конструктора, там даже методу параметров никаких не передается?
|
|
|
Записан
|
ещё один вопрос ...
|
|
|
Alf
Гость
|
|
« Ответ #8 : 11-10-2005 10:28 » |
|
Инициализируется объект один раз в момент создания, а присавивать потом можно сколько угодно раз (при условии, что присваивание определено). Я там в обсуждении привел пример, когда только инициализация применима.
Если у тебя все переменные-члены класса простых типов, не объектные, то разница не столь велика. А если объекты, то инициализация и присваивание могут иметь совершенно различный смысл.
|
|
|
Записан
|
|
|
|
Алексей++
глобальный и пушистый
Глобальный модератор
Offline
Сообщений: 13
|
|
« Ответ #9 : 11-10-2005 10:34 » |
|
ладно, поверим на слово нуна так нуна. Хотя не совсем понятно
|
|
|
Записан
|
|
|
|
nikedeforest
|
|
« Ответ #10 : 11-10-2005 10:40 » |
|
а присавивать потом можно сколько угодно раз (при условии, что присваивание определено) Если у тебя все переменные-члены класса простых типов, не объектные, то разница не столь велика. А если объекты, то инициализация и присваивание могут иметь совершенно различный смысл.
Я так понимаю, это к примеру, если мы перегрузили оператор =, то мы не сможем провести обычное присваивание, а при инициализации оно проведется. Я правильно понял? Или я мыслЮ плохо оформил?
|
|
|
Записан
|
ещё один вопрос ...
|
|
|
Джон
просто
Администратор
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."
|
|
|
Джон
просто
Администратор
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 » |
|
Если быть уж совсем точным, то конструктор без параметров является конструктором по умолчанию. Поэтому его можно не вызывать ни в первом примере, ни во втором, он будет вызван автоматически. Если тебя интересует именно приведенный пример, то в нем совершенно без разницы, где вызывать конструктор базового класса и даже вызывать ли его вообще.
А вот в общем случае, когда конструктор имеет параметры, разница между инициализацией и присваиванием может быть значительной. Так что решай сам - стоит ли тебе делать исключение для конструктора без параметров и изобретать для него особую нотацию или же инициализировать все объекты явно, как положено при хорошем стиле объектного программирования.
|
|
|
Записан
|
|
|
|
Алексей++
глобальный и пушистый
Глобальный модератор
Offline
Сообщений: 13
|
|
« Ответ #14 : 11-10-2005 11:03 » |
|
Разница только в том, что при инициализации СРАЗУ создаётся объект с заданными значениями полей данных. При присваивании - сначала создаётся объект с КАКИМИ-ТО значениями
вот теперь я понял
|
|
|
Записан
|
|
|
|
Алексей++
глобальный и пушистый
Глобальный модератор
Offline
Сообщений: 13
|
|
« Ответ #15 : 11-10-2005 11:04 » |
|
> Так что решай сам - стоит ли тебе делать исключение для конструктора > без параметров думаю не стОит , убедили
|
|
|
Записан
|
|
|
|
LP
Помогающий
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();//здесь (незаконно) второй раз вызывается конструктор базового класса //код }
Допустим, например, в конструкторе базового классе мы динамически выделяем память: Если конструктор будет вызван дважды, то адрес первого блока памяти мы безвозвратно потеряем и получим утечку памяти.
|
|
« Последнее редактирование: 12-10-2005 19:12 от LP »
|
Записан
|
Если эта надпись уменьшается, значит ваш монитор уносят
|
|
|
Finch
Спокойный
Администратор
Offline
Пол:
Пролетал мимо
|
|
« Ответ #17 : 12-10-2005 19:10 » |
|
Здесь еше возможен еше один подводный камень. Когда компилятор видит вызов конструктора, то под это дело он выделяет память на переменные класса. Когда так: CChild::CChild( ) : CParent() { //код }
То компилятор понимает, что этого не требуется делать.
|
|
|
Записан
|
Не будите спашяго дракона. Джаффар (Коша)
|
|
|
LP
Помогающий
Offline
|
|
« Ответ #18 : 12-10-2005 19:20 » |
|
Finch, я не понял, что ты имеешь в виду?
|
|
|
Записан
|
Если эта надпись уменьшается, значит ваш монитор уносят
|
|
|
Finch
Спокойный
Администратор
Offline
Пол:
Пролетал мимо
|
|
« Ответ #19 : 12-10-2005 19:28 » |
|
Я как-то сдуру хотел такое сделать, но вызвать другой конструктор своего же класса. И долго ловил глюк. Почему же у меня переменные не иницилизируются, но при этом в дебаге показывается, что все в порядке. Помог ассемблерный дебаг, который показал, что в начале конструктора компилятор ставит автоматом код на выделение памяти под экземпляр класса. И естественно this был разный.
|
|
« Последнее редактирование: 12-10-2005 19:34 от Finch »
|
Записан
|
Не будите спашяго дракона. Джаффар (Коша)
|
|
|
Джон
просто
Администратор
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
Помогающий
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
Помогающий
Offline
|
|
« Ответ #22 : 06-12-2005 12:53 » |
|
Лучше поздно, чем никогда. В этом коде: 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(); ^
Можно написать еще одну статью про ужасы С++.
|
|
|
Записан
|
Если эта надпись уменьшается, значит ваш монитор уносят
|
|
|
|