﻿# V1114\. Suspicious use of type conversion operator when working with COM interfaces\. Consider using the 'QueryInterface' member function\.

Анализатор обнаружил подозрительное использование оператора преобразования типов при работе с COM\-интерфейсами\.

При такой работе может возникнуть ряд проблем\. Вот некоторые из них:

* Не произойдет увеличения счётчика ссылок\.
* Возможно преобразование в несовместимый тип или интерфейс\. Например, при множественном наследовании, или после изменения версии интерфейса\.
* Возможно нарушение совместимости на уровне ABI\.

Правильным способом работы c COM\-интерфейсами является использование функции '[QueryInterface](https://learn.microsoft.com/en-us/windows/win32/api/unknwn/nf-unknwn-iunknown-queryinterface(refiid_void))', которая специально [предназначена](https://learn.microsoft.com/en-us/windows/win32/com/queryinterface--navigating-in-an-object) для этого\. Причина в том, что COM – независимая от языка программирования технология\. COM\-объекты могут быть реализованы на языках программирования, отличных от C\+\+, а также находиться в адресных пространствах, отличных от адресного пространства вызывающего процесса\.

Функция 'QueryInterface' [должна](https://learn.microsoft.com/en-us/windows/win32/com/rules-for-implementing-queryinterface):

* проверять, что к запрашиваемому интерфейсу можно получить доступ;
* возвращать указатель на запрашиваемый интерфейс;
* увеличивать счётчик ссылок на объект\.

Рассмотрим синтетический пример ошибки\. Допустим, в коде есть COM\-интерфейсы 'IDraw' и 'IShape', которые отвечают за работу с некой геометрической фигурой:

```cpp
interface IDraw : public IUnknown
{
  ....
  virtual HRESULT Draw() = 0;
  ....
};

interface IShape : public IUnknown
{
  ....
  virtual HRESULT GetArea(double *area) = 0;
  ....
};
```

Также у нас есть COM\-объект 'Circle', который имплементирует интерфейсы 'IDraw' и 'IShape':

```cpp
class Circle : public IDraw, public IShape
{
  ....
};
```

Теперь рассмотрим пример неправильной работы с нашим COM\-объектом через интерфейс 'IDraw':

```cpp
void foo(IDraw *ptrIDraw)
{
  IShape *ptrIShape = dynamic_cast<IShape*>(ptrIDraw);
  ....
  if (ptrIShape) 
    ptrIShape->GetArea(area);
  ....
}
```

В примере выше не произойдет увеличение счётчика ссылок на объект типа 'Circle'\. Для увеличения и уменьшения счётчика должны зваться функции '[AddRef](https://learn.microsoft.com/en-us/windows/win32/api/unknwn/nf-unknwn-iunknown-addref)' и '[Release](https://learn.microsoft.com/en-us/windows/win32/api/unknwn/nf-unknwn-iunknown-release)' соответственно\. Поэтому будет правильно воспользоваться функцией 'QueryInterface', которая сама контролирует механизм счётчика ссылок\.

Таким образом, корректный код выглядит так:

```cpp
void foo(IDraw *ptrIDraw)
{
  IShape *ptrIShape = nullptr;
  ....
  if (SUCCEEDED(ptrIDraw->QueryInterface(IID_IShape, &ptrIShape))
  ....
}
```