You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
"Smart pointer parameter is used only to access contained pointer. Use T* or T& instead."
12
12
13
13
**C++ Core Guidelines**:
14
-
R.30: Take smart pointers as parameters only to explicitly express lifetime semantics
14
+
[R.30](https://github.com/isocpp/CppCoreGuidelines/blob/master/CppCoreGuidelines.md#r30-take-smart-pointers-as-parameters-only-to-explicitly-express-lifetime-semantics): Take smart pointers as parameters only to explicitly express lifetime semantics
15
15
16
16
Using a smart pointer type to pass data to a function indicates that the target function needs to manage the lifetime of the contained object. However, if the function only uses the smart pointer to access the contained object and never actually calls any code that may lead to its deallocation (that is, never affect its lifetime), there is usually no need to complicate the interface with smart pointers. A plain pointer or reference to the contained object is preferred.
> Shared pointer parameter is passed by rvalue reference. Pass by value instead.
12
12
13
13
**C++ Core Guidelines**:
14
-
R.34: Take a shared_ptr\<widget> parameter to express that a function is part owner
14
+
[R.34](https://github.com/isocpp/CppCoreGuidelines/blob/master/CppCoreGuidelines.md#r34-take-a-shared_ptrwidget-parameter-to-express-that-a-function-is-part-owner): Take a shared_ptr\<widget> parameter to express that a function is part owner
15
15
16
16
Passing a shared pointer by rvalue reference is usually unnecessary. Unless it is an implementation of move semantics for a shared pointer type itself, shared pointer objects can be safely passed by value. Using rvalue reference may be also an indication that unique pointer is more appropriate since it clearly transfers unique ownership from caller to callee.
> Shared pointer parameter is passed by reference and not reset or reassigned. Use T* or T& instead.
12
12
13
13
**C++ Core Guidelines**:
14
-
R.35: Take a shared_ptr\<widget>& parameter to express that a function might reseat the shared pointer
14
+
[R.35](https://github.com/isocpp/CppCoreGuidelines/blob/master/CppCoreGuidelines.md#r35-take-a-shared_ptrwidget-parameter-to-express-that-a-function-might-reseat-the-shared-pointer): Take a shared_ptr\<widget>& parameter to express that a function might reseat the shared pointer
15
15
16
16
Passing shared pointers by reference may be useful in scenarios where callee code updates target of the smart pointer object and its caller expects to see such update. Using a reference solely to reduce costs of passing a shared pointer is questionable. If callee code only accesses target object and never manages its lifetime, it is safer to pass raw pointer or reference, rather than to expose resource management details.
> Shared pointer parameter is not copied or moved. Use T* or T& instead.
12
12
13
13
**C++ Core Guidelines**:
14
-
R.36: Take a const shared_ptr\<widget>& parameter to express that it might retain a reference count to the object
14
+
[R.36](https://github.com/isocpp/CppCoreGuidelines/blob/master/CppCoreGuidelines.md#r36-take-a-const-shared_ptrwidget-parameter-to-express-that-it-might-retain-a-reference-count-to-the-object-): Take a const shared_ptr\<widget>& parameter to express that it might retain a reference count to the object
15
15
16
16
If shared pointer parameter is passed by value or reference to a constant object it is expected that function will take control of its target object’s lifetime without affecting of the caller. The code should either copy or move the shared pointer parameter to another shared pointer object or pass it further to other code by invoking functions which accept shared pointers. If this is not the case, then plain pointer or reference may be feasible.
"Global initializer calls a non-constexpr function."
12
12
13
13
**C++ Core Guidelines**:
14
-
I.22: Avoid complex initialization of global objects
14
+
[I.22](https://github.com/isocpp/CppCoreGuidelines/blob/master/CppCoreGuidelines.md#i22-avoid-complex-initialization-of-global-objects): Avoid complex initialization of global objects
15
15
16
16
The order of execution of initializers for global objects may be inconsistent or undefined. This can lead to issues that are hard to reproduce and investigate. To avoid such problems, global initializers should not depend on external code that's executed at run time and can potentially depend on data that's not yet initialized. This rule flags cases where global objects call functions to obtain their initial values.
"Symbol is never tested for nullness, it can be marked as gsl::not_null."
13
13
14
14
**C++ Core Guidelines**:
15
-
F.23: Use a not_null\<T> to indicate that "null" is not a valid value
15
+
[F.23](https://github.com/isocpp/CppCoreGuidelines/blob/master/CppCoreGuidelines.md#f23-use-a-not_nullt-to-indicate-that-null-is-not-a-valid-value): Use a not_null\<T> to indicate that "null" is not a valid value
16
16
17
17
It is a common practice to use asserts to enforce assumptions about validity of pointer values. The problem with asserts is that they do not expose assumptions through the interface (e.g. in return types or parameters). Asserts are also harder to maintain and keep in sync with other code changes. The recommendation is to use gsl::not_null from the Guidelines Support Library as a marker of resources which should never have null value. The rule USE_NOTNULL helps to identify places that omit checks for nullness and hence can be updated to use gsl::not_null.
F.23: Use a not_null\<T> to indicate that "null" is not a valid value
15
+
[F.23](https://github.com/isocpp/CppCoreGuidelines/blob/master/CppCoreGuidelines.md#f23-use-a-not_nullt-to-indicate-that-null-is-not-a-valid-value): Use a not_null\<T> to indicate that "null" is not a valid value
16
16
17
17
If code ever checks nullness of pointer variables it should do this consistently and validate pointers on all paths. Sometimes overaggressive checking for nullness is still better than possibility of a hard crash in one of the complicated branches. Ideally such code should be refactored to be less complex (by splitting into multiple functions) and to rely on markers like gsl::not_null (see Guidelines Support Library) to isolate parts of algorithm that can make safe assumption about valid pointer values. The rule TEST_ON_ALL_PATHS helps to find places where nullness checks are either inconsistent (hence assumptions may require review) or actual bugs where potential null value can bypass nullness check in some of the code paths.
"The type of expression is already gsl::not_null. Do not test it for nullness."
13
13
14
14
**C++ Core Guidelines**:
15
-
F.23: Use a not_null\<T> to indicate that "null" is not a valid value
15
+
[F.23](https://github.com/isocpp/CppCoreGuidelines/blob/master/CppCoreGuidelines.md#f23-use-a-not_nullt-to-indicate-that-null-is-not-a-valid-value): Use a not_null\<T> to indicate that "null" is not a valid value
16
16
17
17
The marker type gsl::not_null from Guidelines Support Library is used to clearly indicate values that are never null pointers. It causes a hard failure if such assumption is not held at run time. So, obviously, there is no need to check for nullness if expression evaluates to a result of type gsl::not_null.
"If you define or delete any default operation in the type, define or delete them all."
12
+
> `If you define or delete any default operation in the type 'type-name', define or delete them all (c.21).`
12
13
13
-
**C++ Core Guidelines**:
14
+
**C++ Core Guidelines**:\
14
15
[C.21: If you define or =delete any default operation, define or =delete them all](https://isocpp.github.io/CppCoreGuidelines/CppCoreGuidelines#c21-if-you-define-or-delete-any-default-operation-define-or-delete-them-all)
15
16
16
-
Special operations like constructors are assumed to alter behavior of types so that they rely more on language mechanisms to automatically enforce specific scenarios. The canonical example is resource management. If you explicitly define, default, or delete any of these special operations, it signals you want to avoid any special handling of a type. It's inconsistent to leave the other operations unspecified, that is, implicitly defined as deleted by the compiler.
17
+
Special operations such as constructors are assumed to alter the behavior of types so they rely more on language mechanisms to automatically enforce specific scenarios. The canonical example is resource management. If you explicitly define, default, or delete any of these special operations, it signals you want to avoid any special handling of a type. It's inconsistent to leave the other operations unspecified, that is, implicitly defined as deleted by the compiler.
17
18
18
19
## Remarks
19
20
20
-
- This check implements "the rule of five" which treats the following operations as special:
21
-
- copy constructors;
22
-
- move constructors;
23
-
- copy assignment operators;
24
-
- move assignment operators;
21
+
- This check implements the *rule of five*, which treats the following operations as special:
22
+
- copy constructors,
23
+
- move constructors,
24
+
- copy assignment operators,
25
+
- move assignment operators, and
25
26
- destructors.
26
27
- The rule doesn't check if operations are defined in the same way. It's okay to mix deleted and defaulted operations with explicitly defined ones. However, you must specify all of them if you specify any of them.
27
28
- Access levels aren't important and can also be mixed.
28
29
- The warning flags the first non-static function definition of a type, once per type.
30
+
31
+
## Example
32
+
33
+
In this example, `warning::S` defines only a default constructor and a destructor. The `no_warning::S` declaration defines all five special member functions.
34
+
35
+
```cpp
36
+
// C26432.cpp
37
+
namespacewarning
38
+
{
39
+
struct S
40
+
{
41
+
S() noexcept {}
42
+
~S() {} // C26432 because only the constructor and destructor are explicitly defined.
description: "Microsoft C++ Code Analysis warning C26434 for the C++ Core Guidelines case C.128."
4
+
ms.date: 08/21/2020
4
5
ms.topic: "conceptual"
5
6
f1_keywords: ["C26434"]
6
7
helpviewer_keywords: ["C26434"]
7
8
ms.assetid: 7f66477f-da66-444a-a6e3-44513d7d7e31
8
9
---
9
10
# C26434 DONT_HIDE_METHODS
10
11
11
-
"Function hides a non-virtual function."
12
+
> `Function 'derived::function' hides a non-virtual function 'base::function' (c.128).`
12
13
13
14
## C++ Core Guidelines
14
15
15
16
[C.128: Virtual functions should specify exactly one of virtual, override, or final](https://github.com/isocpp/CppCoreGuidelines/blob/master/CppCoreGuidelines.md)
16
17
17
-
Introducing a function which has the same name as a non-virtual function in a base class is like introducing a variable name which conflicts with a name from outer scope. Furthermore, if signatures of functions mismatch, the intended overriding may turn into overloading. Overall, name hiding is dangerous and error-prone.
18
-
19
18
## Remarks
20
19
21
-
- Only non-overriding functions in current class are checked.
20
+
When you introduce a function that has the same name as a non-virtual function in a base class, you may get unexpected behavior. It's like introducing a variable name which conflicts with a name from an outer scope. For example, you may have intended to override a base class function. If the signatures of the functions don't match, the override you intended may turn into an overload instead. In general, name hiding is dangerous and error-prone.
21
+
22
+
In the Core Guidelines checks:
23
+
24
+
- Only non-overriding functions in the current class are checked.
22
25
- Only non-virtual functions of base classes are considered.
23
26
- No signature matching is performed. Warnings are emitted if unqualified names match.
24
27
25
-
## See also
28
+
## Example
26
29
27
-
[C.128: Virtual functions should specify exactly one of virtual, override, or final](https://github.com/isocpp/CppCoreGuidelines/blob/master/CppCoreGuidelines.md)
30
+
This example demonstrates how a derived class can hide non-virtual functions, and how virtual functions allow both overloads and overrides:
31
+
32
+
```cpp
33
+
// C26434.cpp
34
+
structBase
35
+
{
36
+
virtual ~Base() = default;
37
+
virtual void is_virtual() noexcept {}
38
+
void not_virtual() noexcept {}
39
+
};
40
+
41
+
structDerived : Base
42
+
{
43
+
void is_virtual() noexcept override {} // Okay, override existing function
44
+
virtual void is_virtual(int i) noexcept {} // Add a virtual overload for function
45
+
void not_virtual() noexcept {} // C26434, hides a non-virtual function
0 commit comments