Не переиспользуйте имена во вложенных областях видимости
Причина
Легко запутаться, какая переменная используется. Может создавать проблемы при сопровождении кода.
Пример (плохой)
int d = 0;
// ...
if (cond) {
// ...
d = 9;
// ...
}
else {
// ...
int d = 7;
// ...
d = value_to_be_returned;
// ...
}
return d;
Если это большой оператор if, легко не заметить, что во внутренней области видимости введена новая переменная d. Это известный источник ошибок. Иногда такое повторное использование имени во внутренней области видимости называют «затенением».
Примечание
Затенение — это прежде всего проблема, когда функции слишком большие и слишком сложные.
Пример
Затенение аргументов функции в самом внешнем блоке запрещено языком:
void f(int x)
{
int x = 4; // ошибка: повторное использование имени аргумента функции
if (x) {
int x = 7; // допустимо, но плохо
// ...
}
}
Пример (плохой)
Повторное использование имени члена в качестве локальной переменной тоже может быть проблемой:
struct S {
int m;
void f(int x);
};
void S::f(int x)
{
m = 7; // присваивание члену
if (x) {
int m = 9;
// ...
m = 99; // присваивание локальной переменной
// ...
}
}
Исключение
Мы часто переиспользуем имена функций из базового класса в производном:
struct B {
void f(int);
};
struct D : B {
void f(double);
using B::f;
};
Это чревато ошибками. Например, если бы мы забыли объявление using, вызов d.f(1) не нашёл бы версию f для int.
??? Нужно ли специальное правило о затенении/сокрытии в иерархиях классов?
Контроль
- Отмечайте повторное использование имени в локальных вложенных областях видимости
- Отмечайте повторное использование имени члена в качестве локальной переменной в функции-члене
- Отмечайте повторное использование глобального имени в качестве локальной переменной или имени члена
- Отмечайте повторное использование имени члена базового класса в производном классе (за исключением имён функций)