# V717. It is suspicious to cast object of base class V to derived class U.

Анализатор заметил в коде ситуацию необычного приведения типов: указатель на объект базового класса жёстко приводится к указателю на производный класс. Причём известно, что указатель на базовый класс действительно указывает на объект базового класса.

Приведение указателей производного класса к базовому – вполне типичная ситуация. А вот приведение базового класса к одному из производных, может иногда быть ошибочным. Если приведение типов выполнено неправильно, то попытка обращения к членам производного класса может привести к Access Violation или ко всему чему угодно.

Иногда программисты допускают ошибки, приводя к производному классу указатель именно на базовый класс. Пример из реального приложения:

    typedef struct avatarCacheEntry { .... };
    struct CacheNode : public avatarCacheEntry,
                       public MZeroedObject
    {
      ....
      BOOL   loaded;
      DWORD  dwFlags;
      int    pa_format;
      ....
    };
    avatarCacheEntry tmp;
    ....
    CacheNode *cc = arCache.find((CacheNode*)&tmp);
    // Далее при попытке обращения, например, к
    // cc->loaded, произойдёт ошибка времени выполнения.

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

Следующий код анализатором считается корректным:

    base * foo() { .... }
    derived *y = (derived *)foo();

Здесь дело в том, что функция foo() может на самом деле всегда возвращать указатель на один из производных классов, и приведение её результата к производному классу – вполне обыденное явление. Вообще, анализатор выдаёт предупреждение V717 только в том случае, если точно известно, что именно базовый класс приводится к производному. Однако, анализатор не будет выдавать предупреждение V717 в том случае, если в производном классе нет новых нестатических членов (хотя всё равно так делать нехорошо, но это уже ближе к нарушению хорошего стиля кода, нежели к настоящей ошибке):

    struct derived : public base
    {
      static int b;
      void bar();
    };
    ....
    base x;
    derived *y = (derived *)(&x);

Данная диагностика классифицируется как:

CWE-843