include::../why-general.adoc[] The examples below show typical situations in which shadowing can occur. * Parameter shadowing + [source,cpp] ---- void f(int x, bool b) { int y = 4; if (b) { int x = 7; // Noncompliant: the parameter "x" is shadowed. int y = 9; // Noncompliant: the local variable "y" is shadowed. // ... } } ---- * Member variable shadowing + [source,cpp] ---- class Foo { private: int myField; public: void doSomething() { int myField = 0; // Noncompliant: Foo::myField is shadowed. // ... } }; ---- * Global variable shadowing + [source,cpp] ---- namespace ns { int state; void bar() { int state = 0; // Noncompliant: the namespace variable is shadowed. } } ---- === Exceptions It is common practice to have constructor arguments shadowing the fields they initialize in the _member initializer list_. This pattern avoids the need to select new names for the constructor arguments and will not be reported by this rule. [source,cpp] ---- class Point { public: Point(int x, int y) : x(x) // Compliant by exception: the parameter "x" is used // in the member initializer list. { y = y; // Noncompliant: the parameter is assigned to itself // and the member "y" is not initialized. } private: int x; int y; }; ---- === Caveats ==== Shadowing in `if`, `else if`, and `else` Variables can be introduced in the condition of an `if` statement. Their scope includes the optional `else` statement, which may be surprising. Consequently, such variables can be shadowed in an `else if` statement. This can be even more confusing and result in unintended behavior, as illustrated in this example: [source,cpp] ---- using ExpectedData = std::expected; if (ExpectedData e = readData()) { printMessage(e.value()); } else if (ExpectedData e = readFallbackSource()) { // Noncompliant printMessage(e.value()); } else { logError( "Initial source failed with: ", e.error() // Contrary to the intention, the second "e" is used. ); } ---- ==== Shadowing of inaccessible declarations This rule also raises issues on some variables, although they do not shadow another variable according to a strict interpretation of the {cpp} language. There are mainly two reasons for this. . Primarily, the readability and maintainability of the code are impaired. Readers need an advanced understanding of the {cpp} language to understand the subtle differences. . Secondly, a small change can lead to actual shadowing. This can lead to subtle bugs when updating the code. Here is an example with nested classes: [source,cpp] ---- class A { public: int x; class B; }; class A::B { void f(int x) { // Noncompliant: The parameter "x" shadows the field "A::x". // ... } }; ---- In the above example, `A::x` cannot be used from `A::B` member functions because it is not a `static` field. This can lead to surprising effects when moving code around, particularly if the declaration of `A::x` was changed from `int x;` to `static int x;`. You should always avoid shadowing to avoid any confusion and increase the maintainability of your code. == Resources === External coding guidelines * MISRA C:2004, 5.2 - Identifiers in an inner scope shall not use the same name as an identifier in an outer scope, and therefore hide that identifier * MISRA {cpp}:2008, 2-10-2 - Identifiers declared in an inner scope shall not hide an identifier declared in an outer scope * MISRA C:2012, 5.3 - An identifier declared in an inner scope shall not hide an identifier declared in an outer scope === Standards * CERT - https://wiki.sei.cmu.edu/confluence/display/c/DCL01-C.+Do+not+reuse+variable+names+in+subscopes[DCL01-C. Do not reuse variable names in subscopes] === Related rules * S2387 - Child class fields should not shadow parent class fields include::../rspecator.adoc[]