Для реализации подсчета ссылок мы используем IUnknown
- как интерфейс и класс шаблона умного указателя. В интерфейсе реализованы все методы подсчета ссылок, включая Release()
:
void IUnknownLike::Release()
{
if( --refCount == 0 ) {
delete this;
}
}
Класс шаблона интеллектуального указателя имеет конструктор копирования и оператор присваивания, оба принимают необработанные указатели. Таким образом, пользователи могут делать следующее:
class Class : public IUnknownLike {
};
void someFunction( CSmartPointer<Class> object ); //whatever function
Class object;
someFunction( &object );
и программа работает с неопределенным поведением - объект создается с нулевым счетчиком ссылок, создается интеллектуальный указатель и переводит его в единицу, затем функция возвращается, интеллектуальный указатель уничтожается, вызывает Release()
, что приводит к delete
переменной, распределенной в стеке. .
Пользователи также могут делать следующее:
struct COuter {
//whatever else;
Class inner;// IUnknownLike descendant
};
COuter object;
somefunction( &object.Inner );
и снова объект, не созданный с помощью new
, равен delete
d. Неопределенное поведение в лучшем виде.
Есть ли способ изменить интерфейс IUnknownLike
, чтобы пользователь был вынужден использовать new
для создания всех объектов, производных от IUnknownLike
- как прямо производных, так и косвенно производных (с классами между наиболее производными и базовыми)?