2014-07-25 124 views
0

这个程序为什么写入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; 
} 

的静态数组乙arrB[N]和d arrD[N]似乎这里造成麻烦。

+1

125Σ₍ᵢ₌₁₀₎¹⁹(I) – chris

+6

并没有发生什么,当您使用断点和观察值调试的应用程序? – RvdK

+0

当我调试时,它不会去构造函数让我看看b和d的值是什么。 但我想出了另一种调试方式,Bb是0 1 2 3 4 5 6 7 8 9,Db是10 11 12 13 14 15 16 17 18 19,Dd是11 12 13 14 15 16 17 18 19 20.结果125是10 + 11 + 11 + 12 + 12 + 13 + 13 + 14 + 14 + 15,但我不知道为什么这些值。 – anicicn

回答

9

数组不是多态的;只有当期望单个元素时,才可以将D*传递给期望B*的函数。 (尝试使用std::vector,你会得到一个编译时错误。)原因很简单:访问数组元素所需的指针算术是基于指向元素的静态大小,所以每次你在执行i++sum1循环,然后索引,编译器计算您的元素的地址为arr + i * sizeof(B)(在机器级别,其中arr是纯粹的无类型地址)。

当静态类型与动态类型不一样时,试图做指针算术是未定义的行为,所以就语言而言,任何事情都可能发生。

而这又是另一个原因而不是使用C风格的数组。

+0

是的。很好的解释。这是有道理的 - 当像你这样的人这样讲时,听起来很容易。谢谢。 – anicicn

6

问题是数组不包含指向对象的指针,而是包含整个对象。 所以,当你通过一个指向基类的指针使用D数组时,(如詹姆斯指出的那样),行为是不确定的。

实际上在大多数系统上可能发生的情况:基于指针的循环只迭代D对象的一半以上,因为B对象只包含一个int,而D对象包含它们中的两个。

所以循环如下仅在第一5 d对象:

b/d 
10/11 
11/12 
12/13 
13/14 
14/15 

其总结于不祥125

+0

可能。行为是不确定的,事实上,任何事情都可能发生。如果他向B添加了一个虚拟析构函数(如果推导的话,推荐使用这个析构函数),结果可能(也可能会)完全不同。 –

+0

你说得对,我稍微更新了答案。 – Steffen

+0

是的。当有虚拟功能时,真正的乐趣开始发生,并且你在循环中调用一个。(当然,在大多数机器上,只是将其中一种数据类型改为'double'会导致非常奇怪的结果。) –

1

我认为将D数组转换为B数组是不正确的。步幅不正确。这就是为什么你会看到这些重复的价值观。

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; 
} 
+0

你应该提供原因而不是说“你会知道原因”。 – djv

相关问题