
Update all links to C++ Core Guidelines to `e49158a`.
Refresh done using the following script and some manual edits:
db76e34e74/personal/fred-tingaud/rspec/refresh-cppcoreguidelines.py
When re-using this script, be mindful that:
- it does not cover `shared_content`
- it does not properly escape inline code in links (e.g., "[=]" or "`mutex`es")
- it does not change `C++` to `{cpp}` in link titles.
Co-authored-by: Marco Borgeaud <marco.borgeaud@sonarsource.com>
81 lines
2.2 KiB
Plaintext
81 lines
2.2 KiB
Plaintext
== Why is this an issue?
|
||
|
||
Casting a base-class pointer/reference to a derived-class pointer/reference is commonly referred to as downcasting which can only be done using an explicit cast.
|
||
|
||
However, the use of ``++static_cast++`` for such a cast is unsafe because it doesn't do any runtime check. If the cast memory doesn't contain an object of the expected derived type, your program enters the undefined behavior territory.
|
||
|
||
|
||
If your object is polymorphic, you might prefer using ``++dynamic_cast++`` instead, as it allows safe downcasting by performing a run-time check:
|
||
|
||
* If the cast memory contains an object of the expected derived type, the check succeeds. The result of the ``++dynamic_cast++`` points/refers to the derived object.
|
||
* If the cast memory doesn't contain an object of the expected derived type, the check fails. If the ``++dynamic_cast++`` is used on a pointer, ``++nullptr++`` is returned. If it was used on a reference, ``++std::bad_cast++`` is thrown.
|
||
|
||
This rule raises an issue when ``++static_cast++`` is used for downcasting.
|
||
|
||
|
||
=== Noncompliant code example
|
||
|
||
[source,cpp]
|
||
----
|
||
struct Shape {
|
||
virtual ~Shape();
|
||
// ...
|
||
};
|
||
|
||
struct Rectangle : public Shape {
|
||
double width;
|
||
double height;
|
||
};
|
||
|
||
struct Circle : public Shape {
|
||
double radius;
|
||
};
|
||
|
||
double computeArea(const Shape* shape) {
|
||
const auto* rectangle = static_cast<const Rectangle*>(shape); // Noncompliant
|
||
return rectangle->width * rectangle->height;
|
||
}
|
||
----
|
||
|
||
|
||
=== Compliant solution
|
||
|
||
[source,cpp]
|
||
----
|
||
struct Shape {
|
||
virtual ~Shape();
|
||
// ...
|
||
};
|
||
|
||
struct Rectangle : public Shape {
|
||
double width;
|
||
double height;
|
||
};
|
||
|
||
struct Circle : public Shape {
|
||
int radius;
|
||
};
|
||
|
||
double computeArea(const Shape* shape) {
|
||
if(const auto* rectangle = dynamic_cast<const Rectangle*>(shape)) { // Compliant
|
||
return rectangle->width * rectangle->height;
|
||
}
|
||
return 0;
|
||
}
|
||
----
|
||
|
||
|
||
== Resources
|
||
|
||
* {cpp} Core Guidelines - https://github.com/isocpp/CppCoreGuidelines/blob/e49158a/CppCoreGuidelines.md#prosafety-type-safety-profile[Type.2: Don’t use `static_cast` to downcast]
|
||
|
||
|
||
ifdef::env-github,rspecator-view[]
|
||
'''
|
||
== Comments And Links
|
||
(visible only on this page)
|
||
|
||
=== relates to: S5823
|
||
|
||
endif::env-github,rspecator-view[]
|