为什么这个程序会写45,125和300? 我知道45和300,我对一个案例sum1(arrD)更感兴趣,程序写入125。 我希望有人知道。
#include <iostream>
using namespace std;
class B{
public:
B(): b(bCounter++){}
int b;
static int bCounter;
};
int B::bCounter = 0;
class D : public B{
public:
D() : d(bCounter){}
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;
}
int main(){
cout<<" result is: "<<sum1(arrB)<<endl;
cout<<" result is: "<<sum1(arrD)<<endl;
cout<<" result is: "<<sum2(arrD)<<endl;
system("pause");
return 0;
}
静态数组B arrB[N]
和D arrD[N]
似乎在这里引起了麻烦。
答案 0 :(得分:9)
阵列不是多态的;只有在需要单个元素时,才能将D*
传递给期望B*
的函数。 (尝试使用std::vector
,你会得到一个编译时错误。)原因很简单:访问数组元素所需的指针算法是基于指向元素的静态大小,所以每次你在i++
的循环中执行sum1
,然后编制索引,编译器将元素的地址计算为arr + i * sizeof(B)
(在机器级别,arr
是纯的,无类型地址)。
当静态类型与动态类型不同时,尝试进行指针运算是未定义的行为,因此就语言而言,任何事情都可能发生。
这是不使用C样式数组的另一个原因。
答案 1 :(得分:6)
问题是数组不包含指向对象的指针而是包含整个对象的指针。 因此,当您通过指向基类的指针使用D数组时(如James所述),行为未定义。
在大多数系统中实际上可能会发生什么:基于指针的循环只迭代D对象的一半,因为B对象只包含一个int
,而D对象包含其中两个。
因此循环只查看前5个D对象:
b / d
10/11
11/12
12/13
13/14
14/15
总计不祥的125。
答案 2 :(得分:1)
我认为将D数组转换为B数组是不正确的。步幅不正确。这就是为什么你会看到这些重复的价值观。
答案 3 :(得分:0)
运行以下代码,您将知道原因
#include <iostream>
using namespace std;
class B{
public:
B(): b(bCounter++){
cout<<"B called\n";
}
int b;
static int bCounter;
};
int B::bCounter = 0;
class D : public B{
public:
D() : d(bCounter){
cout<<"D called\n";
}
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++)
{
cout<<arr[i].b<<"\n";
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;
}
int main(){
//cout<<" result is: "<<sum1(arrB)<<endl;
cout<<" result is: "<<sum1(arrD)<<endl;
//cout<<" result is: "<<sum2(arrD)<<endl;
system("pause");
return 0;
}