AUTOSAR C++14 Rule A8-4-14

Интерфейсы должны быть точно и со строгим контролем типов

Описание

Управляйте определением

Интерфейсы должны быть точно и со строгим контролем типов.

Объяснение

Интерфейсы описывают поведение или возможности объекта. Точно и интерфейсы со строгим контролем типов задают цель и свойства их параметров при помощи параметров, которые являются пользовательскими объектами и шаблонами вместо фундаментальных типов. Сравните интерфейсы в этом фрагменте кода:

void draw_circle(float R, float x, float y);
void draw_circle(Length R, Position O);
Оба интерфейса представляют функцию, которая рисует круг. Первый интерфейс использует три плавающих числа в качестве входных параметров. Второй интерфейс использует объект класса Length и другой объект класса Position как входные параметры.

  • Второй интерфейс делает его явным, что первый параметр является длиной, и второй параметр является положением. Этот интерфейс легко изучить и использовать, потому что он подсвечивает необходимые входные параметры и их порядок для определенного круга. В отличие от этого, вы не можете различить входные параметры или их порядок в первом интерфейсе, потому что не ясно, как три плавающих числа относятся к кругу.

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

  • Определение классов Length и Position может задать модули этих параметров, такие как cm или мм. Определения классов могут также задать, являются ли эти параметры неизменяемыми. Когда вы используете фундаментальные типы в качестве входных параметров, такая спецификация затрудняет.

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

Когда несколько параметров связаны, комбинируют их в пользовательский тип. При реализации полиморфных интерфейсов используйте указатели на общий базовый класс вместо указателей на пустоту (void*). Для типовых интерфейсов используйте шаблоны в качестве параметров.

Реализация Polyspace

В Polyspace® эти типы являются фундаментальными типами:

  • Целочисленные типы, такие как int, short, и long

  • Типы с плавающей точкой, такие как float или double

  • Булевская переменная (bool) типы

  • Указатели на пустоту (void*)

  • Указатели или ссылки на предыдущие типы

  • typedef из предыдущих типов

  • Массивы предыдущих типов

В Polyspace, перечислениях или enums не фундаментальные типы. Polyspace отмечает интерфейс, если его входные параметры включают какое-либо следующее:

  • Один или несколько void связанные типы

  • Два или больше bool связанные типы

  • Три или больше идентичных фундаментальных типа

Можно использовать альтернативы, такие как комментарии или названия параметра, чтобы разъяснить интерфейсное определение. В таких случаях можно выровнять по ширине результат Polyspace при помощи комментариев в результате или кода. Смотрите Результаты Polyspace Адреса Через Исправления ошибок или Выравнивания

Поиск и устранение проблем

Если вы ожидаете нарушение правила, но не видите его, обратитесь к Кодированию Стандартных Нарушений, Не Отображенных.

Примеры

развернуть все

Polyspace отмечает интерфейсы, когда их входные параметры включают:

  • Два или больше bool связанные типы

  • Три или больше идентичных фундаментальных типа

Рассмотрите интерфейсы в этом коде:

#include <cstdint>
#include <chrono>

void Sleep(std::uint32_t duration);//Compliant

void SetProperty(bool Status);//Compliant

void SetAlarm(std::uint32_t year, std::uint32_t month, //Noncompliant
              std::uint32_t day, std::uint32_t hour,
              std::uint32_t minute, std::uint32_t second);

//Compliant
void StartClock(std::chrono::system_clock::time_point const& when);
typedef struct {
    int a, b, c, d;
} Point;
void Triangle(float a, float b, float c);//Noncompliant
void Rectangle(Point a, Point b, Point c, Point d); //Compliant

main()
{
    //...
}

  • Polyspace отмечает интерфейсы, которые используют три или больше переменные фундаментального типа в качестве входных параметров, таких как SetAlarm() и Triangle().

  • Интерфейсы StartClock() и Rectangle() используйте точные и входные параметры со строгим контролем типов. Polyspace не отмечает эти интерфейсы.

  • Polyspace не отмечает интерфейс, который имеет меньше чем три входных параметра фундаментального типа или меньше чем два bool введите входные параметры.

Polyspace отмечает интерфейсы, когда их входные параметры включают один или несколько указателей на пустоту (void*). Рассмотрите интерфейсы в этом коде:

#include <cstdint>

class A{
	//...
};
class B:public A{
	//...
};
class C:public A{
	//...
};

void polymorphic_function(void*);//Noncompliant
void polymorphic_function(A*);//Compliant

void printArray(void* Array);//Noncompliant
template <typename T>
void printArray (T* Array);//Compliant

main(){
	//...
}

Все типы указателей неявно преобразуют в void*, который является слабым и недостаточно квалифицированным типом. Избегайте использования void* указатели.

  • Чтобы реализовать полиморфные интерфейсы, используйте указатели на базовые классы, такие как A* вместо void*.

  • Чтобы реализовать типовые интерфейсы, используйте шаблоны, такие как T* вместо void*.

Проверяйте информацию

Группа: операторы объявления
Категория: необходимый, неавтоматизированный