Reputation: 193
Why does this program write 45, 125 and 300? I know for 45 and 300, I'm more interested in a case sum1(arrD), where program writes 125. I hope somebody will know.
#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;
}
The static arrays B arrB[N]
and D arrD[N]
seem to be causing the trouble here.
Upvotes: 0
Views: 132
Reputation: 436
Run following code , you'll know the reason
#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;
}
Upvotes: 0
Reputation: 1621
I think it's incorrect to cast an array of D to an array of B. The stride isn't correct. This is why you see these repeats of values.
Upvotes: 1
Reputation: 2948
The problem is that the arrays do not contain pointers to the objects but whole objects. So when you use the D array via a pointer to the base class, (as James noted) the behaviour is undefined.
What in practice probably happens on most systems: The pointer-based loop only iterates over half the D objects, because a B object contains only one int
, while the D objects contain two of them.
So the loop looks only at the first 5 D objects:
b / d
10/11
11/12
12/13
13/14
14/15
which sums up to the ominous 125.
Upvotes: 6
Reputation: 153929
Arrays aren't polymorphic; you can pass a D*
to a function expecting a B*
only if it expects a single element. (Try using std::vector
, and you'll get a compile time error.) The reason is simple: the pointer arithmetic needed to access the array elements is based on the static size of the pointed to element, so each time you do i++
in the loop in sum1
, and then index, the compiler calculates the address of your element as arr + i * sizeof(B)
(at the machine level, where arr
is a pure, untyped address).
Trying to do pointer arithmetic when the static type is not the same as the dynamic type is undefined behavior, so as far as the language is concerned, anything can happen.
And this is yet another reason not to use C style arrays.
Upvotes: 9