﻿# Тонкость с виртуальными функциями

Решил записать один момент, связанный с виртуальными функциями, а то боюсь, что потом его забуду и случайно вновь вернусь к этому вопросу :\)\.

В анализаторе Viva64 есть диагностика ошибок, возникающих в 64\-битном коде, когда у виртуальных функций изменяется тип аргумента\. Подробнее это описано в документации к продукту здесь: [V301](https://pvs-studio.ru/ru/docs/warnings/v301/)\.

Вот пример кода, где анализатор выдаст эти предупреждения:

```cpp
class A
{
public:
  virtual int x(unsigned) { return 1; }
  virtual int y(__int64) { return 2; }
};
class B : public A
{
public:
  int x(size_t) { return 3; } //V301
  int y(ptrdiff_t) { return 4; } //V301
};
void Use()
{
  A *p = new B;
  cout <<p->x(1) << " " <<p->y(1) << endl;
  delete p;
}
```

В 32\-битном режиме на печать будет выдано "3 2", а в 64\-битном режиме "1 4"\. Ошибки в данном коде успешно диагностируются анализатором Viva64\. Но недавно меня посетила мысль, что необходимо диагностировать не только изменяющиеся аргументы виртуальных функций, но и возвращаемый аргумент\. В голове у меня возник следующий пример, который следует диагностировать как ошибочный:

```cpp
class A
{
public:
  virtual int x() {};
};
class B : public A
{
public:
  ptrdiff_t x() {};
};
```

К счастью такой вариант в 64\-битном режиме просто не скомпилируется и соответственно не возникнет ошибки связанной с изменением поведения кода\. Компилятор Visual C\+\+ выдает ошибку:

error C2555: 'B::x': overriding virtual function return type differs and is not covariant from 'A::x' : see declaration of 'A::x'

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

Рассмотрим последний момент, связанный с диагностикой функций, где отличается как аргумент, так и возвращаемый тип:

```cpp
class A
{
public:
  virtual int x(int) { return 1; }
};
class B : public A
{
public:
  ptrdiff_t x(ptrdiff_t) { return 2; } //V301
};
```

Данный код компилируется и содержит ошибку\. Анализатор Viva64 корректно разбирается в подобной ситуации и предупреждает, что аргумент изменяет свой тип в 64\-битной системе\. После исправления этой ошибки, компилятор откажется компилировать код и будет исправлена вторая ошибка \- тип возвращаемого аргумента\.