exponenta event banner

Правило AUTOSAR C++ 14 A8-4-14

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

Описание

Определение правила

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

Объяснение

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

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

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

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

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

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

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

Внедрение Polyspace

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

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

  • Типы с плавающей запятой, например float или double

  • Булев (bool) типы

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

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

  • typedef предшествующих типов

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

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

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

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

  • Три или более идентичных основных типов

Для уточнения определения интерфейса можно использовать альтернативные варианты, такие как комментарии или имена параметров. В таких случаях можно обосновать результат 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 (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*.

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

Группа: Деклараторы
Категория: Обязательные, неавтоматические