2023-05-03 11:06:20 +02:00
== Why is this an issue?
2021-04-28 16:49:39 +02:00
A base class and its derived class often differ in size.
Accessing an array of a derived class through a pointer to the base class leads to wrong pointer arithmetic and can then corrupt memory.
2021-04-28 18:08:03 +02:00
2023-05-03 11:06:20 +02:00
=== Noncompliant code example
2021-04-28 16:49:39 +02:00
2022-02-04 17:28:24 +01:00
[source,cpp]
2021-04-28 16:49:39 +02:00
----
struct Base { /*...*/};
struct Derived : public Base { /*...*/};
void f(Base const &b);
int main() {
const size_t size = 4;
Derived derivedArray[size];
Base* basePointer = derivedArray; // Noncompliant
f(basePointer[2]); // The arithmetic will use the size of Base, not the size of Derived, and point to a random byte in the array
}
----
If you need to do a cast from derived to base in an array, do it element by element.
2021-04-28 18:08:03 +02:00
2023-05-03 11:06:20 +02:00
=== Compliant solution
2021-04-28 16:49:39 +02:00
2022-02-04 17:28:24 +01:00
[source,cpp]
2021-04-28 16:49:39 +02:00
----
#include<iostream>
using namespace std;
struct Base {
int iBase = 0;
};
struct Derived : public Base {
int iDerived = 0;
};
int main() {
const size_t size = 4;
Derived derivedArray[size];
for(int i=0; i<size; ++i) {
derivedArray[i].iBase = i; // store : 0 1 2 3
derivedArray[i].iDerived = i*1000;
}
for(int i=0; i<size; ++i) {
cout<<"derivedArray["<<i<<"].iBase="<<derivedArray[i].iBase<<endl; // display : 0 1 2 3
cout<<"base of derivedArray["<<i<<"].iBase="<<static_cast<Base*>(derivedArray+i)->iBase<<endl; // display : 0 1 2 3
}
return 0;
}
----
2021-04-28 18:08:03 +02:00
2023-05-03 11:06:20 +02:00
== Resources
2021-04-28 16:49:39 +02:00
2023-12-20 10:08:18 +01:00
* {cpp} Core Guidelines - https://github.com/isocpp/CppCoreGuidelines/blob/e49158a/CppCoreGuidelines.md#c152-never-assign-a-pointer-to-an-array-of-derived-class-objects-to-a-pointer-to-its-base[C.152: Never assign a pointer to an array of derived class objects to a pointer to its base]
2021-04-28 18:08:03 +02:00
2021-06-02 20:44:38 +02:00
2021-06-03 09:05:38 +02:00
ifdef::env-github,rspecator-view[]
2021-06-08 15:52:13 +02:00
'''
2021-06-02 20:44:38 +02:00
== Comments And Links
(visible only on this page)
2023-05-25 14:18:12 +02:00
=== relates to: S5410
=== on 25 Oct 2019, 16:27:29 Geoffray Adde wrote:
First, we try a much stronger, constraining and simpler version of the rule: no array (C-style, std::array and std::vector) of publicly derived class.
=== on 18 Dec 2019, 17:55:05 Loïc Joly wrote:
If you want to try the stronger version, why not directly document it? I think it might have value on its own, as a code smell... And I would also prevent arrays of base classes.
2021-06-03 09:05:38 +02:00
endif::env-github,rspecator-view[]