Модераторы: Daevaorn

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> constructor/destructor, кто виртуальней? 
:(
    Опции темы
scarlett
Дата 8.7.2005, 02:14 (ссылка)    |    (голосов: 0) Загрузка ... Загрузка ... Быстрая цитата Цитата


Unregistered











Подскажите пожалуйста, почему виртуальный конструктор не имеет смысла, а виртуальный деструктор - это хорошо.
  Вверх
Alexey Dejneka
Дата 8.7.2005, 04:21 (ссылка)    |    (голосов: 0) Загрузка ... Загрузка ... Быстрая цитата Цитата


Unregistered











В Objective C
  Вверх
adejneka
Дата 8.7.2005, 04:43 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 105
Регистрация: 8.7.2005
Где: Москва, Россия

Репутация: нет
Всего: 11



В Objective C и CLOS конструкторы виртуальные, но они принадлежат метаклассам.

В C++ нет (не было?) объектов-классов, соответственно, послать сообщение "создать экземпляр" некому.
PM MAIL   Вверх
chaos
Дата 8.7.2005, 07:09 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Серийный программист
****


Профиль
Группа: Завсегдатай
Сообщений: 2979
Регистрация: 7.7.2004
Где: Екатеринбург

Репутация: 6
Всего: 44



Цитата(scarlett @ 8.7.2005, 02:14)
Подскажите пожалуйста, почему виртуальный конструктор не имеет смысла, а виртуальный деструктор - это хорошо.

виртуальный конструктор не имеет смысла тк при создании объекта необходимо знать сколько места под него выделять
а виртуальный деструктор правельно освободит место занимаемое объектом(при наследовании)


вот еще можешь почитать про вк
Цитата

Эта идиома предложена Джеймсом Коплином (James Coplien), который назвал ее «виртуальным
конструктором».
Что делает следующий перегруженный оператор new?
class Foo {
public:
  void* operator new(size_t, void* p) { return p; }
};

На первый взгляд — ничего; пустая трата времени. Но так ли это? Что произойдет в следующем
фрагменте?

union U {
  Foo foo;
  Bar bar;
  Banana banana;
};
U whatIsThis;

Компилятор С++ не может определить, какой конструктор следует вызывать для whatIsThis —Foo::Foo(), Bar::Bar() или Banana::Banana(). Разумеется, больше одного конструктора вызывать нельзя, поскольку все члены занимают одно и то же место в памяти, но без инструкций от вас
не может выбрать нужный конструктор. Как и во многих других ситуациях, компилятор поднимет руки; он сообщает об ошибке и отказывается принимать объединение, члены которого имеют
конструкторы. Если вы хотите, чтобы одна область памяти могла инициализироваться несколькими различными способами, придется подумать, как обмануть компилятор. Описанный выше «пустой»
конструктор подойдет лучше всего.
unsigned char space[4096];
Foo* whatIsThis = new(&space[0]) Foo;
Фактически происходит то, что в С++ происходить не должно — вызов конструктора. При этом память на выделяется и не освобождается, поскольку оператор new ничего не делает. Тем не менее, компилятор С++ сочтет, что это новый объект, и все равно вызовет конструктор. Если позднее вы передумаете и захотите использовать ту же область памяти для другого объекта, то сможете снова вызвать хитроумный оператор new и инициализировать ее заново. При создании объекта оператором new компилятор всегда использует двухшаговый процесс:
1. Выделение памяти под объект.
2. Вызов конструктора объекта.
Этот код запрятан в выполняемом коде, генерируемом компилятором, и в обычных ситуациях второй шаг не выполняется без первого. Идиома виртуального конструктора позволяет надеть повязку на глаза
компилятору и обойти это ограничение.

Джефф Элджер C++ БИБЛИОТЕКА ПРОГРАММИСТА

Это сообщение отредактировал(а) chaos - 8.7.2005, 07:50
PM WWW   Вверх
Chaos A.D.
Дата 8.7.2005, 08:08 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


Профиль
Группа: Участник
Сообщений: 172
Регистрация: 16.1.2005
Где: 09 RUS

Репутация: 6
Всего: 7



Весь прикол в том, что в С++ статическая система типов. Тут нет объектов классов. Для того, чтобы создать объект, оператор new должен знать тип объекта, который нужно создать. Статическая типизация - одна из причин эффективности С++. Тем не менее, в С++, как всегда, найдется обходной путь (:. Языковые средства не поддерживают виртуальных конструкторов, как тут было сказано, но это не значит, что их суть нельзя выразить на С++. chaos приводил пример из книги. Но это не столько виртуальный конструктор, сколько хитрое использование оператора размещения ( new(void*)(...) ). К настоящим виртуальным конструкторам по принципу действия приближаются фабрики объектов. Они основаны на диспетчеризации вызовов функций, которые создают объекты разных типов. Таким образом, если отображать идентификатор типа в тип, можно создавать объекты этого типа по этому идентификатору. Идентификатором может быть строковое представление названия класса, или еще что-нибудь. Если говорить менее пафосно - можно замутить ассоциацию строки, скажем "Foo" с функцией или объектом, который создает объект класса Foo. И все в таком же духе. Вот это уже больше похоже на виртуальные функции. Ну а главная польза от них заключается, на мой взгляд, в повышении масштабируемости, и увеличении модульности. Вот так.
--------------------
Надо смеяться над тем, что тебя мучит, иначе не сохранишь равновесия, иначе мир сведет тебя с ума...Ken Kesey - One Flew Over The Cocoo's Nest
PM MAIL   Вверх
np9mi7
  Дата 8.7.2005, 08:09 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 553
Регистрация: 17.8.2003
Где: Volgograd, Russia

Репутация: 5
Всего: 10



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

Это сообщение отредактировал(а) np9mi7 - 8.7.2005, 08:23


--------------------
"Я точно знаю то, что ничего не знаю..." Сократ.
evolution project
PM MAIL WWW ICQ MSN   Вверх
Chaos A.D.
Дата 8.7.2005, 08:31 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


Профиль
Группа: Участник
Сообщений: 172
Регистрация: 16.1.2005
Где: 09 RUS

Репутация: 6
Всего: 7



Цитата(np9mi7 @ 8.7.2005, 08:09)
потому как ты должен знать что конструируешь, или ты и в жизни как: дай мне то не знаю что...., компилятоор за тебя не подумает что сконструировать....

Бывает и так... Например, говоришь фабрике объектов - дай мне такой widget, который был, когда я сохранял его в файл. Тогда компилер смотрит в файл, видит там идентификатор виджета, и возвращает настоящий виджет, производный от абстрактного Widget. Это, конечно, не совсем "дай мне то не знаю что", но очень похоже. Примерно, как "Дай мне что-то, похожее на это. И чтоб еще то-то умело."
--------------------
Надо смеяться над тем, что тебя мучит, иначе не сохранишь равновесия, иначе мир сведет тебя с ума...Ken Kesey - One Flew Over The Cocoo's Nest
PM MAIL   Вверх
Vyacheslav
Дата 8.7.2005, 09:49 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Экс. модератор
Сообщений: 2124
Регистрация: 25.3.2002
Где: Москва

Репутация: 9
Всего: 59



Цитата(chaos @ 8.7.2005, 07:09)
а виртуальный деструктор правельно освободит место занимаемое объектом(при наследовании)

ответ неполный smile . Во время интервьюирования при приеме на работу такой ответ вызовет дополнительные вопросы.
обычный деструктор также правильно освобождает память при наследовании
Код

сlass A {
private:
  char* bufA;
  A::A()
     :bufA(new char[1000]) { }
  A::~A(){delete bufA;}
};
сlass B : public A {
private:
  char* bufB;
  B::B()
     :A(),bufB(new char[1000]) { }
  B::~B(){delete bufB;}
};


B* pb = new B;
delete B;




--------------------
С уважением, Вячеслав Ермолаев
PM MAIL WWW ICQ   Вверх
np9mi7
  Дата 8.7.2005, 10:05 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 553
Регистрация: 17.8.2003
Где: Volgograd, Russia

Репутация: 5
Всего: 10



Цитата
Тогда компилер смотрит в файл,
, компилятор не смотрит, смотрит исполняемый файл...
а в фабрике у тебя что:

Код

switch(_type)
{
case 1:
{
return new Object1();
}
case 2:
{
return new Object2();
}
case 3:
{
return new Object3();
}
}

, так или иначе ты должен сказать кого создать

Цитата
обычный деструктор также правильно освобождает память при наследовании
, зачем тогда виртуальность в деструкторах?

А если так:
Код

A* pb = new B;
delete pb;

, что вызывается без виртуальности?

Это сообщение отредактировал(а) np9mi7 - 8.7.2005, 10:09


--------------------
"Я точно знаю то, что ничего не знаю..." Сократ.
evolution project
PM MAIL WWW ICQ MSN   Вверх
Vyacheslav
Дата 8.7.2005, 10:16 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Экс. модератор
Сообщений: 2124
Регистрация: 25.3.2002
Где: Москва

Репутация: 9
Всего: 59



По фабрике
http://forum.vingrad.ru/index.php?showtopi...indpost&p=60738


Цитата(np9mi7 @ 8.7.2005, 10:05)
зачем тогда виртуальность в деструкторах?

Для поддержки механизма полиморфизма

Если полимофизм использовать не предполагается, то применение виртуальных функций (в том числе и деструкторов) излишние накладные расходы.



--------------------
С уважением, Вячеслав Ермолаев
PM MAIL WWW ICQ   Вверх
Chaos A.D.
Дата 8.7.2005, 16:03 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


Профиль
Группа: Участник
Сообщений: 172
Регистрация: 16.1.2005
Где: 09 RUS

Репутация: 6
Всего: 7



Цитата(np9mi7 @ 8.7.2005, 10:05)
, компилятор не смотрит, смотрит исполняемый файл...


Ну это ты уже придираешься smile. А по поводу switch-ей в фабрике - так это просто кощунство.
--------------------
Надо смеяться над тем, что тебя мучит, иначе не сохранишь равновесия, иначе мир сведет тебя с ума...Ken Kesey - One Flew Over The Cocoo's Nest
PM MAIL   Вверх
np9mi7
  Дата 9.7.2005, 13:09 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 553
Регистрация: 17.8.2003
Где: Volgograd, Russia

Репутация: 5
Всего: 10



Цитата
А по поводу switch-ей в фабрике - так это просто кощунство.
, ну подскажите как нужно? Вообще сама фраза сама по себе не корректна - кощунство, что такое фабрика? Или мы говорим о фабричном методе? Так или иначе задача фабрики на основе своих данных сконструировать объект и отдать клиенту только интерфейс ( классически - абстрактный класс). А вот как она там будет конструировать, как делать свой выбор что создать это её дело. Здесь switch для примера, не более того, но иногда бывают ситуации когда и без него никак (кстати в примерах Гамма приводит фабрику со switch);

Цитата
Для поддержки механизма полиморфизма
, если Вы в своем примере:
Код

A* pb = new B;
delete pb;
, не напишите виртуальный деструктор то вызовется деструктор для A... Что ни есть правильно....

Цитата
Если полимофизм использовать не предполагается, то применение виртуальных функций (в том числе и деструкторов) излишние накладные расходы.
, но они вполне окупаются если нужно писать быстро и маштабируемо (посмотрите на Class Wizard - ы многих IDE (VS 6.0 например), так они по умолчанию все деструкторы виртуальными делают);

Это сообщение отредактировал(а) np9mi7 - 9.7.2005, 13:25


--------------------
"Я точно знаю то, что ничего не знаю..." Сократ.
evolution project
PM MAIL WWW ICQ MSN   Вверх
Chaos A.D.
Дата 11.7.2005, 07:17 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


Профиль
Группа: Участник
Сообщений: 172
Регистрация: 16.1.2005
Где: 09 RUS

Репутация: 6
Всего: 7



Цитата(np9mi7 @ 9.7.2005, 13:09)
А по поводу switch-ей в фабрике - так это просто кощунство.
... ну подскажите как нужно?

Я бы реализовал фабрику с использованием ассоциативного массива, состоящего из пар "индекс типа"-"вызываемая сущность, создающая объект". Отлично подойдут функторы(обобщенные), или простые указатели на функции. Например, будучи проиндексированным строкой "Foo", массив вернул бы то, к чему можно применить оператор (), и получить указатель на класс Foo. Естесственно, Foo должен быть полиморфным, иначе вообще ни к чему фабрики использовать. По моему, да и не только по моему, нужно так.

Цитата(np9mi7 @ 9.7.2005, 13:09)
... Вообще сама фраза сама по себе не корректна - кощунство, что такое фабрика? Или мы говорим о фабричном методе? Так или иначе задача фабрики на основе своих данных сконструировать объект и отдать клиенту только интерфейс ( классически - абстрактный класс). А вот как она там будет конструировать, как делать свой выбор что создать это её дело. Здесь switch для примера, не более того, но иногда бывают ситуации когда и без него никак (кстати в примерах Гамма приводит фабрику со switch);


Не, я против switch-а ничего лично не имею, однако оно основано на статических метках, и поэтому категорически запрещено к использованию в ОО программах.

По поводу книги GoF - она издавалась в далеком 1995 году; с тех пор концепции объектно-ориентированного программирования претерпели значительные изменения. С введением в стандарт языка такой вещи, как шаблонов, появилась возможность выражать алгоритмы и концепции независимо от типов, с которыми предполагается её использовать. Конечно, фабрика, основанная на switch-конструкциях, все-же фабрика, однако, крайне немасштабируема. Гамма использовал switch наверное потому, что тогда шаблоны были только-только включены в стандарт. Кстати, товарищ Александреску выразил все паттерны из книги независимо от типов, за что ему респект от всей программистской братии. Советую обратить внимание на библиотеку Loki.

Это сообщение отредактировал(а) Chaos A.D. - 11.7.2005, 07:20
--------------------
Надо смеяться над тем, что тебя мучит, иначе не сохранишь равновесия, иначе мир сведет тебя с ума...Ken Kesey - One Flew Over The Cocoo's Nest
PM MAIL   Вверх
Vyacheslav
Дата 11.7.2005, 16:25 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Экс. модератор
Сообщений: 2124
Регистрация: 25.3.2002
Где: Москва

Репутация: 9
Всего: 59



Цитата(np9mi7 @ 9.7.2005, 13:09)
но они вполне окупаются если нужно писать быстро и маштабируемо (посмотрите на Class Wizard - ы многих IDE (VS 6.0 например), так они по умолчанию все деструкторы виртуальными делают);


Это как раз и отличает визарды от программистов. Первые как правило работают бездумно smile

Цитата(np9mi7 @ 9.7.2005, 13:09)
, если Вы в своем примере:


Код

A* pb = new B;
delete pb;


не напишите виртуальный деструктор то вызовется деструктор для A... Что ни есть правильно....

Полиморфизм - "имеющий много форм". Применительно к ООП, это означает способность объектов выбирать метод на основе реального типа объекта при обращении к нему как к некоторому общему интерфейсу. Так что этот пример - типичный пример использования полиморфизма. А вот этот нет( здесь программист сам указывает какой деструктор нужно вызвать)
Код

A* pb = new B;
delete (B*)pb;

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







--------------------
С уважением, Вячеслав Ермолаев
PM MAIL WWW ICQ   Вверх
np9mi7
  Дата 12.7.2005, 11:08 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 553
Регистрация: 17.8.2003
Где: Volgograd, Russia

Репутация: 5
Всего: 10



Цитата
Конечно, фабрика, основанная на switch-конструкциях, все-же фабрика, однако, крайне немасштабируема. Гамма использовал switch наверное потому, что тогда шаблоны были только-только включены в стандарт.
, привеоди пример фабрики от _type (те создание от типа - причем тип определяется некоторым значением - integer например) которая использует приемущества шаблонов;
Цитата
что тогда шаблоны были только-только включены в стандарт.
, когда они были включены стандарт?

Цитата
Я бы реализовал фабрику с использованием ассоциативного массива, состоящего из пар "индекс типа"-"вызываемая сущность, создающая объект". Отлично подойдут функторы(обобщенные), или простые указатели на функции. Например, будучи проиндексированным строкой "Foo", массив вернул бы то, к чему можно применить оператор (), и получить указатель на класс Foo. Естесственно, Foo должен быть полиморфным, иначе вообще ни к чему фабрики использовать. По моему, да и не только по моему, нужно так.
, ты уверен что операция:
1) индексирования по массиву;
2) обращения к VT;

длиться быстрее чем switch? Недором ведь switch можно делать только по встроенным типам....

Цитата
Не, я против switch-а ничего лично не имею, однако оно основано на статических метках, и поэтому категорически запрещено к использованию в ОО программах.
, эта метка в одном месте - в фабричном методе... Где тут нарушение концепций ООP?

Цитата
Виртуальный деструктор предназначен для корректного разрушения объекта при применении полиморфизма. и следовательно, как и виртуальные функции предназначен для поддержки последнего.
, согласен. Не знаешь что за объект->интерфейс есть->нужно убить->убиваешь правильно через нужный деструктор;

Цитата
Это как раз и отличает визарды от программистов. Первые как правило работают бездумно smile
, разработчики wizard - ов, наверное предполагают что пользователь wizard - ов будет использовать все приемущества IDE ( например бавовый класс TObject или СObject), так что тут дело не в бездумности: хочешь приемущество в скорости разработки на выбранной IDE или нет smile

Это сообщение отредактировал(а) np9mi7 - 12.7.2005, 11:10


--------------------
"Я точно знаю то, что ничего не знаю..." Сократ.
evolution project
PM MAIL WWW ICQ MSN   Вверх
Ответ в темуСоздание новой темы Создание опроса
Правила форума "С++:Общие вопросы"
Earnest Daevaorn

Добро пожаловать!

  • Черновик стандарта C++ (за октябрь 2005) можно скачать с этого сайта. Прямая ссылка на файл черновика(4.4мб).
  • Черновик стандарта C (за сентябрь 2005) можно скачать с этого сайта. Прямая ссылка на файл черновика (3.4мб).
  • Прежде чем задать вопрос, прочтите это и/или это!
  • Здесь хранится весь мировой запас ссылок на документы, связанные с C++ :)
  • Не брезгуйте пользоваться тегами [code=cpp][/code].
  • Пожалуйста, не просите написать за вас программы в этом разделе - для этого существует "Центр Помощи".
  • C++ FAQ

Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, Earnest Daevaorn

 
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | C/C++: Общие вопросы | Следующая тема »


 




[ Время генерации скрипта: 0.0573 ]   [ Использовано запросов: 22 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.