Итак, опробовал метод по навешиванию трапа на оператор присваивания. Не вдаваясь в подробности реализации перехватчиков, таким вот примерно макаром:
class myCValue: public CValue
{
public:
CValue const &OperatorAssign(CValue const &Source);
};
CTrap trapOperatorAssign("bkend.dll", "??4CValue@@QAEABV0@ABV0@@Z", GetMethAddr(&myCValue::OperatorAssign));
// public: class CValue const & __thiscall CValue::operator=(class CValue const &)
CValue const &myCValue::OperatorAssign(CValue const &Source)
{
if (Source.m_TypeCode==0) return Reset(),*this;
CTrapSwap Swap(trapOperatorAssign);
return (this->*trapOperatorAssign.Old(&OperatorAssign))(Source);
}
Работает прекрасно. Причём одним махом решает все описанные проблемы (и неописанные тоже). Только вот убивает меня вешать трап на такую часто вызываемую вещь, как оператор присваивания, поскольку может сказаться на производительности, которая итак не фонтан. Есть идея слить весь его код, полностью подменив оригинальный, и поправить по собственному вкусу (опыт такой был уже, так что думаю проблем не возникнет). Займусь на досуге...
Работает, но не так уж и прекрасно. Уже объявились нюансы. Например, можно оператором присваивания затереть ссылку на исполняемый модуль. Если сделать это не с помощью пустого значения (а любого другого), трап восстановит исходную версию кода и вызовет родной оператор. Тот, в свою очередь, потрёт ссылку, модуль начнёт уничтожаться, а там объекты всякие с деструкторами. Деструкторы начнут работать, выполняя всякий код, а оператор присваивания при этом будет уже родной со всеми вытекающими... Короче, не канает такой метод, только полное дублирование кода оператора с необходимыми изменениями.