CQM-HalfHeartedOperation

Related routine clusters should be implemented completely or consistently

Required inputs: IR

This rule checks for rule of three violations, missing virtual destructors in classes that contain at least one virtual routine and opposite operators that are not implemented in term of each other.
Motivation

Certain routines of classes must be kept consistent with each other with regard to their implementation, since clients of the class rely on this consistency. If the behavior of individual methods is changed by new implementations or the use of different bindings (virtual vs. non-virtual), this consistency can be destroyed, i.e., the functionality underlying the routine group can become incorrect as a result.

While consistency of application code implementation cannot be expressed in general terms, there are, however, the following specific rules on the part of programming languages that should be observed:

  • Java
    • Keeping Object.equals() and Object.hashCode() consistent, because collection classes first identify equivalence candidates using hashCode.
  • C++
    • operator++(void) and operator++(int) (or operator--) together to ensure consistency between post and prefix operators.
    • Implement Copy constructor and operator= together.
    • If a class has a virtual method, then the class must also have a virtual destructor.

This means in each case that the change of one of these methods must imply the change of the others.

This rule is based on the CQM Quality Indicator: halbherzige Operationen (p. 207-210).

Reference

Simon, Frank/ Seng, Olaf/ Mohaupt, Thomas (2006): Code-Quality-Management: Technische Qualität industrieller Softwaresysteme transparent und vergleichbar gemacht, 1st ed., Heidelberg, Germany: dpunkt.verlag GmbH.

Possible Messages

Key

Text

Severity

Disabled

implement_in_terms

Implement in terms of other operator

None

False

missing_constructor_and_asgn

Class with destructor should also declare a copy or move constructor and assignment operator.

None

False

missing_copy_asgn

Class with copy constructor is missing copy assignment operator.

None

False

missing_copy_constructor

Class with copy assignment operator is missing copy constructor.

None

False

missing_destructor

Class with copy or move constructors or assignment operators should also declare a destructor.

None

False

missing_move_asgn

Class with move constructor is missing move assignment operator.

None

False

missing_move_constructor

Class with move assignment operator is missing move constructor.

None

False

missing_virtual_destructor

Class needs a virtual destructor.

None

False

Options

accept_none_destructor

accept_none_destructor : bool = False

If set true, classes without any destructor are tolerated.
 

allow_defaulted_destructor_only

allow_defaulted_destructor_only : bool = True

Allow classes with a defaulted destructor and no other special member functions.
 

allow_destructor_only

allow_destructor_only : bool = False

Allow all destructors without copy or move constructors
 

allow_empty_destructor

allow_empty_destructor : bool = True

Allow empty destructors without copy or move constructors.
 

allow_missing_destructor

allow_missing_destructor : bool = False

Suppress messages about missing destructors.
 

allow_protected_destructor_only

allow_protected_destructor_only : bool = False

Allow a protected destructor without copy or move constructors
 

ignore_classes_ending_with_string

ignore_classes_ending_with_string : set[str] = set()

Do not report a class name that ends with one of the given strings.
 

ignore_classes_inheriting_from

ignore_classes_inheriting_from : set[bauhaus.analysis.config.QualifiedName] = set()

Do not report a class that inherits from one of the given classes.
 

ignore_classes_with_member_type

ignore_classes_with_member_type : set[bauhaus.analysis.config.QualifiedName] = set()

Do not report a class that has a member with one of the given types.
 

ignore_macro_expanded_classes

ignore_macro_expanded_classes : set[bauhaus.analysis.config.MacroName] = set()

Do not report a class expanded via one of the given macro names.
 

ignore_pod_classes

ignore_pod_classes : bool = True

Whether POD classes should be checked at all.