Код:
class B {
public:
B () : b(++bCounter) {}
int b;
static int bCounter;
};
int B::bCounter = 0;
class D : public B {
public:
D () : d(0) {}
int d;
};
const int N = 10;
B arrB[N];
D arrD[N];int sum1 (B* arr) {
int s = 0;
for (int i=0; i<N; i++)
{
s+=arr[i].b;
}
return s;
}
int sum2 (D* arr) {
int s = 0;
for (int i=0; i<N; i++)
{
s+=arr[i].b+arr[i].d;
}
return s;
}
Вопрос:
Что они возвращают:
1) sum1(arrB)
знак равно
2) sum1(arrD)
знак равно
3) sum2(arrD)
знак равно
Когда я компилирую & запустить их, я получаю 55, 65 и 155, и понятия не имею, почему. Я понимаю, что в arrB переменные b = 1,2,3, …, 10, а в arrD b = 11,12, …, 20, поэтому я бы ответил на sum1 (arrB) = 55 и sum1 (arrD) = 155, как в сумме 11 + 12 + .. + 20, и sum2 (arrD) = 155, потому что везде d = 0.
Что я делаю неправильно?
Вы получаете нарезку объектов.
Вы передаете D*
массив в функцию, которая принимает B*
массив. D
изначально больше чем B
,
Каждый раз, когда вы делаете s+=arr[i].b;
вы двигаете указатель по размеру B, в то время как вам нужно переместить его по размеру D, поэтому после каждой итерации указатель не перемещается ни на один элемент вперед.
[TheBPart|TheDPart][TheBPart|TheDPart][TheBPart|TheDPart]
^
|
iteration 0
[TheBPart|TheDPart][TheBPart|TheDPart][TheBPart|TheDPart]
^
|
iteration 1
[TheBPart|TheDPart][TheBPart|TheDPart][TheBPart|TheDPart]
^
|
iteration 2
[TheBPart|TheDPart][TheBPart|TheDPart][TheBPart|TheDPart]
^
|
iteration 3
Что происходит в вашем конкретном случае, так это то, что после каждой нечетной итерации он указывает где-то в средний объекта D
учебный класс. Это происходит только потому, что D
ровно вдвое больше, чем B
иначе поведение было бы другим.
Проблема заключается в преобразовании arrD
в arrB
, B имеет размер 4 байта, в то время как D имеет размер 8 байтов.
Когда вы конвертируете D * в B *, вы фактически перепрыгиваете в памяти 4 байта за итерацию, а не 8 байтов. arrD будет хранить следующие значения в памяти, если мы берем 4 байта за раз
11 // arrD[0].b
0 // arrD[0].d
12 // arrD[1].b
0 // arrD[1].d
13 // arrD[2].b
0 // arrD[2].d
14 // arrD[3].b
0 // arrD[3].d
15 // arrD[4].b
0 // arrD[4].d
16 // arrD[5].b
0 // arrD[5].d
17 // arrD[6].b
0 // arrD[6].d
18 // arrD[7].b
0 // arrD[7].d
19 // arrD[8].b
0 // arrD[8].d
20 // arrD[9].b
0 // arrD[9].d
Теперь, когда вы суммируете 4 байта за раз, вы берете первые 10 значений этого. Следовательно, ваш результат: 11 + 0 + 12 + 0 + 13 + 0 + 14 + 0 + 15 + 0 = 65
Из аналогичных рассуждений вы можете узнать причину своего результата для sum2
,