Почему мой деструктор никогда не называют?

Во-первых, необходимо отметить, что mixins только существуют на языках множественного наследования. Вы не можете сделать смешивания в Java или C#.

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

Mixins являются обычно узкими в объеме и не предназначенные, чтобы быть расширенными.

[редактирование - относительно почему:]

я предполагаю, что должен обратиться, почему, так как Вы спросили. Большое преимущество - то, что Вы не должны делать этого сами много раз. В C# самое большое место, где смешивание могло извлечь выгоду, могло бы быть от шаблон Распоряжения . Каждый раз, когда Вы реализуете IDisposable, Вы почти всегда хотите следовать за тем же шаблоном, но Вы заканчиваете тем, что писали и переписали тот же абсолютный код с незначительными изменениями. Если бы было растяжимое смешивание Распоряжения, то Вы могли бы сохранить себя большой дополнительный ввод.

[редактируют 2 - для ответа на другие вопросы]

, Что разделяет смешивание от множественного наследования? Это - просто вопрос семантики?

Да. Различием между смешиванием и стандартным множественным наследованием является просто вопрос семантики; класс, который имеет множественное наследование, мог бы использовать смешивание как часть того множественного наследования.

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

Снова, думайте об интерфейсе, который уже реализован.

я лично не использую mixins, так как я разрабатываю, прежде всего, на языке, который не поддерживает их, таким образом, мне действительно тяжело придумывать достойный пример, который просто предоставит это "ahah!" момент для Вас. Но я попробую еще раз. Я собираюсь использовать пример, который это изобрело - большинство языков уже обеспечивает функцию так или иначе - но это, надо надеяться, объяснит, как mixins, как предполагается, создаются и используются. Здесь идет:

предположим у Вас есть тип, который Вы хотите смочь сериализировать к и от XML. Вы хотите, чтобы тип предоставил метод "ToXML", который возвращает строку, содержащую фрагмент XML со значениями данных типа и "FromXML", который позволяет типу восстанавливать свои значения данных от фрагмента XML в строке. Снова, это - изобретенный пример, поэтому возможно, Вы используете поток файла или Класс для записи XML от библиотеки времени выполнения Вашего языка... без разницы. Дело в том, что Вы хотите сериализировать свой объект к XML и вернуть новый объект от XML.

другой важный момент в этом примере - то, что Вы хотите сделать это универсальным способом. Вы не хотите должными быть реализовывать "ToXML" и метод "FromXML" для каждого типа, который Вы хотите сериализировать, Вы хотите некоторые универсальные средства обеспечения, что Ваш тип сделает это, и это просто работает. Вы хотите повторное использование кода.

, Если Ваш язык поддерживал его, Вы могли бы создать XmlSerializable mixin, чтобы сделать Вашу работу для Вас. Этот тип реализовал бы ToXML и методы FromXML. Это было бы, с помощью некоторого механизма, это не важно для примера, быть способным к сбору всех необходимых данных из любого типа, что это смешано в с создать фрагмент XML, возвращенный ToXML, и это было бы одинаково способно к восстановлению тех данных, когда FromXML называют.

И..именно. Для использования его у Вас был бы любой тип, который должен быть сериализирован к XML, наследовались XmlSerializable. Каждый раз, когда необходимо было сериализировать или десериализовать тот тип, Вы просто назовете ToXML или FromXML. На самом деле, так как XmlSerializable является абсолютным типом и полиморфный, Вы могли очевидно создать сериализатор документа, который ничего не знает о Вашем исходном типе, принимая только, скажем, массив типов XmlSerializable.

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

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

, Надо надеяться. :)

12
задан Herb Slotinsky 22 August 2009 в 08:52
поделиться

4 ответа

Вашему базовому классу нужен виртуальный деструктор. В противном случае деструктор производного класса не будет вызываться, если используется только указатель типа A *.

Добавьте

virtual ~A() {};

к классу A.

36
ответ дан 2 December 2019 в 03:11
поделиться

Класс A должен иметь виртуальный деструктор. Без этого деструкторы производного класса не будут вызываться.

7
ответ дан 2 December 2019 в 03:11
поделиться

попробуйте следующее:

class A
{
public:
    virtual ~A() {}
    virtual f();
};

class B : public A
{
public:
     B()
     {
         p = new char [100];
     }
     virtual ~B() // virtual keywork optional but occasionally helpful for self documentation.
     {
         delete [] p;
     }
     f();
private:
    char *p;
};
3
ответ дан 2 December 2019 в 03:11
поделиться

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

Добавьте пустой деструктор в A

virtual ~ A () {}

, и это должно исправить это.

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

3
ответ дан 2 December 2019 в 03:11
поделиться
Другие вопросы по тегам:

Похожие вопросы: