类数组总和、索引和计算

class arrays sums, indexes, and calculation

本文关键字:索引 计算 数组      更新时间:2023-10-16

代码:

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 个字节。 如果我们一次占用 4 个字节,arrD 将在内存中保存以下值

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 .