Это вызовет проблему с различными средами выполнения с DLL? - PullRequest
0 голосов
/ 10 января 2011

Мое графическое приложение поддерживает полиморфные синхронизированные события, поэтому пользователь вызывает новый, а графический интерфейс удаляет. Это может создать проблему, если среда выполнения несовместима.

Итак, мне сказали, что предлагаемое решение будет таким:

class base;

class Deallocator {
    void operator()(base* ptr) 
    {
        delete ptr;
    }
}

class base {
public:
base(Deallocator dealloc) 
{
    m_deleteFunc = dealloc;
}
~base() 
{
    m_deleteFunc(this);
}

private:
Deallocator m_deleteFunc;
}

int main
{
    Deallocator deletefunc;

    base baseObj(deletefunc);
}

Хотя это хорошее решение, оно требует, чтобы пользователь создал объект Deallocator, который мне не нужен. Однако мне было интересно, если бы я предоставил Deallocator для каждого производного класса: например,

class derived : public base
{
  Deallocator dealloc;
public:
  Derived() : base(dealloc);
{
}
};

Я думаю, что это все еще не работает, хотя. Ограничение таково: Функция addTimedEvent () является частью класса Widget, который также находится в dll, но создается пользователем. Другое ограничение заключается в том, что некоторые классы, производные от Widget, вызывают эту функцию со своими собственными классами событий по времени.

Учитывая, что «тот, кто вызвал new, должен вызвать delete», что может сработать, учитывая эти ограничения?

Спасибо

Ответы [ 3 ]

1 голос
/ 10 января 2011

Я предлагаю вам изучить парадигму подсчета ссылок COM (AddRef и Release).Это обеспечивает более гибкое время жизни и гарантирует, что используется правильный деаллокатор, поскольку объект удаляется сам.

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

0 голосов
/ 10 января 2011

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

Например:

// Widget header

class base;
namespace {
  inline void default_deleter(base* p) 
  { 
    delete p; 
  }
}

class Widget
{
public:
  addTimedEvent(base* event, void(*deleter)(base*));
};

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

Редактировать: Сделал функцию удаления членом анонимного пространства имен. Это необходимо, чтобы избежать нарушений ODR.
Без пространства имен вы получаете две функции default_deleter, которые имеют одинаковое внешнее имя (поэтому они одинаковы для компоновщика), но с разной семантикой, поскольку они ссылаются на разные деаллокаторы.
С анонимным пространством имен все экземпляры default_deleter становятся отдельными объектами для компоновщика. Это имеет (к сожалению) побочный эффект, что вы больше не можете использовать функцию в качестве аргумента по умолчанию для addTimedEvent.

0 голосов
/ 10 января 2011

Первое, что приходит на ум, это дать базовому классу виртуальный (абстрактный?) SelfDestruct метод.Предполагая, что потребитель вашей DLL передает класс, который он сам получил, он будет знать, как его освободить.

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

Я не уверен, объяснил ли я свою идею очень четко ... если нет, пожалуйста, спросите, я 'позже предоставлю код.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...