Ошибки кодирования конструктора C ++ - PullRequest
2 голосов
/ 01 декабря 2008

Я только что наткнулся на эту ошибку в каком-то устаревшем коде:

class MyAPIHandler
{
    private:
     int handle;
    public:
    void MyApiHandler()  // default constructor
    {
        handle = 42;
    };
};

Он компилируется нормально, без предупреждений, - но поведение было не тем, что я хотел, потому что имя конструктора - ошибка. Это само по себе привело бы к предупреждению о том, что «функция не возвращает значение», но я думаю, что я был на автопилоте и добавил тип возврата «void», чтобы «исправить» это.

Теперь исправление было простым, но мой вопрос таков: -

Какие приемы можно использовать для предотвращения повторения подобных ошибок?

В некоторых языках требуется явное ключевое слово «конструктор», что должно сделать эту проблему очевидной. Модульное тестирование, очевидно, также должно было его поймать. Что еще я могу сделать?

Ответы [ 13 ]

19 голосов
/ 01 декабря 2008

Если вы всегда используете списки инициализаторов в своих конструкторах:

MyApiHandler()  // default constructor
: handle(42)
{
}

ошибка конструктора с неправильным названием будет еще более маловероятной, и в любом случае лучше стиль .

Редактировать : спасибо комментатору за ссылку

2 голосов
/ 01 декабря 2008

Это не должно быть большой проблемой. Конструкторы не имеют возвращаемых значений (даже не void), поэтому компилятор должен иметь возможность определить, что-то должно быть конструктором или функцией-членом, и сообщить вам, если есть проблема. Очевидно, что кто-то увидел ошибку компилятора и выбрал неправильное решение (добавив тип возврата вместо исправления орфографии). (РЕДАКТИРОВАТЬ: Извините, не понял, что вы сделали это самостоятельно.)

Лично я всегда помещаю конструктор (ы) в начале открытого раздела класса (перед любыми функциями-членами, но после определений и констант открытого типа), поэтому такая проблема была бы для меня очевидна при -читание кода. Но условности в этом отличаются.

2 голосов
/ 01 декабря 2008

Помимо того, что вы осторожны или имеете отзывы о коде, вы не можете сделать сделать.

Вы можете составить контрольный список для написания новых классов с такими темами, как:

  • Скопируйте и вставьте имя класса, которое будет использоваться в качестве первого конструктора.
  • Если вы реализуете конструктор копирования, реализуйте деструктор и оператор присвоения копии ( Правило трех .
  • Будьте осторожны с конструкторами с одним аргументом или конструкторами с аргументами по умолчанию - рассмотрите возможность сделать их явными

Это точки, связанные с конструктором, весь контрольный список может быть длиннее. Через некоторое время вы начнете делать такие вещи автоматически.

Лично я считаю, что модульное тестирование - лучший ответ, чтобы избежать вашей конкретной проблемы, как вы уже упоминали.

РЕДАКТИРОВАТЬ: Добавлена ​​идея из комментариев:
В некоторых средах разработки вы можете использовать шаблоны кода или макросы для создания правильного скелета класса. Это настоящее «решение программиста» - автоматизация всего, что можно автоматизировать, чтобы избежать ошибок.

2 голосов
/ 01 декабря 2008

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

1 голос
/ 17 марта 2009

Если переменная-член не собирается изменяться, объявите ее const, и компилятор заставит вас использовать список инициализатора, который в этом случае заставит вас обнаружить вашу ошибку (потому что она не будет компилироваться).

1 голос
/ 01 декабря 2008

Полагаю, вам не следует слишком много думать об этой проблеме

Это происходит для конструкторов, но также для любого другого метода или даже функции. Например:

class MyBase
{
   // etc.
   virtual void doSomething() ;
} ;

class MyDerived : public MyBase
{
   // etc.
   virtual void DoSomething() ;
} ;

Или:

bool isOk(int value) { /* etc. */ }
bool isOK(double value) { /* etc. */ }

void doSomething(int value)
{
   if(isOK(value)) // isOK(double) will be called
   {
      // Etc.
   }
}

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

А как насчет КОНСТРУКТОРА?

Что касается определения КОНСТРУКТОРА, упомянутого до меня, это плохая идея ИМХО:

Это поможет так же, как комментарий (и поэтому, почему бы не использовать / * CONSTRUCTOR * / вместо этого?), И если кто-то подумал об использовании слова CONSTRUCTOR в качестве определяющего символа, то вы можете поспорить, что кто-то другой будет иметь та же идея в каком-то заголовке, который вы включаете, но не владеете, и что он сломает ваш код ...

1 голос
/ 01 декабря 2008

Я почти уверен, что PC Lint, инструмент статического анализа кода, обнаружил бы эту ошибку. Это не бесплатно, но это очень, очень хорошо. Стоит посмотреть:

http://www.gimpel.com/

0 голосов
/ 02 января 2009

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

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

0 голосов
/ 01 декабря 2008

Большинство IDE допускают какие-либо макросы. Просто используйте макрос для создания определения класса. Вот так у меня это настроено. Мой макрос печатает ауты:

class CHANGETHIS
{
    public: 
      CHANGETHIS();
      ~CHANGETHIS();
}
#error "Finish this class definition"

Строка #error - это просто защитная сетка, позволяющая убедиться, что она не сработает, если меня прервут в середине моей работы и забудут об этом, когда вернусь.

Что мне нравится в этом, так это то, что он переносится на любой редактор, поэтому я не чувствую себя инвалидом, когда переключаюсь на другую IDE. Надеюсь, это поможет.

Кроме того, используйте списки инициализации. Они быстрее и приводят к меньшему количеству ошибок.

0 голосов
/ 01 декабря 2008

У меня есть набор жетонов / шаблонов (в Vim ... но я думаю, вы можете использовать их в любом современном редакторе), который позволяет избежать опечаток такого рода.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...