CERT C++: DCL53-CPP

Не пишите синтаксически неоднозначные объявления

Описание

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

Не пишите синтаксически неоднозначный declarations.[1]

Реализация Polyspace

Это средство проверки проверяет на Неоднозначный Синтаксис Объявления.

Примеры

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

Проблема

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

Например, эти объявления неоднозначны:

  • ResourceType aResource();

    Это не сразу понятно если aResource функция, возвращающая переменную типа ResourceType или объект типа ResourceType.

  • TimeKeeper aTimeKeeper(Timer());

    Это не сразу понятно если aTimeKeeper объект, созданный с безымянным объектом типа Timer или функция с указателем функции без имени вводит как параметр. Указатель функции относится к функции без аргумента, и возвратитесь, вводят Timer.

Риск

В случае неоднозначного объявления Стандарт C++ выбирает определенную интерпретацию синтаксиса. Например:

  • ResourceType aResource();
    интерпретирован как объявление функционального aResource.

  • TimeKeeper aTimeKeeper(Timer());
    интерпретирован как объявление функционального aTimeKeeper параметром без имени типа указателя функции.

Если вы или другой разработчик или рецензент кода ожидаете различную интерпретацию, результаты могут быть неожиданными.

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

Фиксация

Сделайте объявление однозначным. Например, зафиксируйте эти неоднозначные объявления можно следующим образом:

  • ResourceType aResource();

    Объектное объявление:

    Если объявление относится к объекту, инициализированному конструктором по умолчанию, перепишите его как:

    ResourceType aResource;
    до C++ 11, или как:
    ResourceType aResource{};
    после C++ 11.

    Объявление функции:

    Если объявление относится к функции, используйте определение типа для функции.

    typedef ResourceType(*resourceFunctionType)();
    resourceFunctionType aResource;

  • TimeKeeper aTimeKeeper(Timer());

    Объектное объявление:

    Если объявление относится к объекту aTimeKeeper инициализированный безымянным объектом класса Timer, добавьте дополнительную пару круглой скобки:

    TimeKeeper aTimeKeeper( (Timer()) );
    до C++ 11, или фигурные скобки использования:
    TimeKeeper aTimeKeeper{Timer{}};
    после C++ 11.

    Объявление функции:

    Если объявление относится к функциональному aTimeKeeper параметром без имени типа указателя функции используйте именованный параметр вместо этого.

    typedef Timer(*timerType)();
    TimeKeeper aTimeKeeper(timerType aTimer);

Пример – функциональное или объектное объявление
class ResourceType {
      int aMember;
    public:
      int getMember();
};

void getResource() {
    ResourceType aResource();
}

В этом примере, aResource может использоваться в качестве объекта, но синтаксис объявления указывает на объявление функции.

Коррекция — использование {} для объектного объявления

Одна возможная коррекция (после C++ 11) должна использовать фигурные скобки для объектного объявления.

class ResourceType {
      int aMember;
    public:
      int getMember();
};

void getResource() {
    ResourceType aResource{};
}
Пример – безымянный объект или объявление параметра функции без имени
class MemberType {};

class ResourceType {
      MemberType aMember;
    public:
      ResourceType(MemberType m) {aMember = m;}
      int getMember();
};

void getResource() {
    ResourceType aResource(MemberType()); 
}

В этом примере, aResource может использоваться в качестве объекта, инициализированного безымянным объектом типа MemberType но синтаксис объявления указывает на функцию параметром без имени типа указателя функции. Указатель функции указывает на функцию без аргументов и типа MemberType.

Коррекция — использование {} для объектного объявления

Одна возможная коррекция (после C++ 11) должна использовать фигурные скобки для объектного объявления.

class MemberType {};

class ResourceType {
      MemberType aMember;
    public:
      ResourceType(MemberType m) {aMember = m;}
      int getMember();
};

void getResource() {
    ResourceType aResource{MemberType()};
}
Пример – безымянный объект или названное объявление параметра функции
class Integer {
       int aMember;
    public:
       Integer(int d) {aMember = d;}
       int getMember();
};

int aInt = 0;
Integer aInteger(Integer(aInt));

В этом примере, aInteger может быть объект, созданный с безымянным объектом Integer(aInt) (объект класса Integer который самостоятельно создается с помощью переменной aInt). Однако синтаксис объявления указывает на тот aInteger функция именованным параметром aInt из типа Integer (лишняя круглая скобка проигнорирована).

Коррекция — использование {} для объектного объявления

Одна возможная коррекция (после C++ 11) должна использовать {} для объектного объявления.

class Integer {
       int aMember;
    public:
       Integer(int d) {aMember = d;}
       int getMember();
};

int aInt = 0;
Integer aInteger{Integer{aInt}};
Коррекция — удаляет лишнюю круглую скобку для именованного объявления параметра

Если aInteger функция именованным параметром aInt, удалите лишнее () вокруг aInt.

class Integer {
       int aMember;
    public:
       Integer(int d) {aMember = d;}
       int getMember();
};

Integer aInteger(Integer aInt);

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

Группа: 01. Объявления и инициализация (DCL)
Введенный в R2019a

[1]  Это программное обеспечение было создано MathWorks, включающим фрагменты: “Веб-сайт SEI CERT-C”, © 2017 Carnegie Mellon University, веб-сайт SEI CERT-C © 2017 Carnegie Mellon University”, CERT SEI C Кодирование Стандарта – Правил для Разработки безопасных, Надежных и Защищенных систем – 2 016 Выпусков”, © 2016 Carnegie Mellon University, and “CERT SEI Стандарт Кодирования C++ – Правил для Разработки безопасных, Надежных и Защищенных систем на C++ – 2 016 Выпусков” © 2016 Carnegie Mellon University, со специальным разрешением от его Института программной инженерии.

ЛЮБОЙ МАТЕРИАЛ УНИВЕРСИТЕТА КАРНЕГИ-МЕЛЛОН И/ИЛИ ЕГО ИНСТИТУТА ПРОГРАММНОЙ ИНЖЕНЕРИИ СОДЕРЖАЛ, ЗДЕСЬ ПРЕДОСТАВЛЯЕТСЯ НА ОСНОВЕ "ASIS". УНИВЕРСИТЕТ КАРНЕГИ-МЕЛЛОН НЕ ДАЕТ ГАРАНТИЙ НИКАКОГО ВИДА, ИЛИ ОПИСАЛ ИЛИ ПОДРАЗУМЕВАЛ, ОТНОСИТЕЛЬНО ЛЮБОГО ВОПРОСА ВКЛЮЧАЯ, НО НЕ ОГРАНИЧИЛ, ГАРАНТИЯ ПРИГОДНОСТИ ДЛЯ ЦЕЛИ ИЛИ ВЫСОКОГО СПРОСА, ИСКЛЮЧИТЕЛЬНОСТИ, ИЛИ ЗАКАНЧИВАЕТСЯ ПОЛУЧЕННЫЙ ИЗ ИСПОЛЬЗОВАНИЯ МАТЕРИАЛА. УНИВЕРСИТЕТ КАРНЕГИ-МЕЛЛОН НЕ ДАЕТ ГАРАНТИИ НИКАКОГО ВИДА ОТНОСИТЕЛЬНО СВОБОДЫ ОТ ПАТЕНТА, ТОВАРНОГО ЗНАКА ИЛИ НАРУШЕНИЯ АВТОРСКОГО ПРАВА.

Это программное обеспечение и сопоставленная документация не были рассмотрены, ни являются подтвержденным Университетом Карнеги-Меллон или его Институтом программной инженерии.