【问题标题】:Why does this program create an output like this?为什么这个程序会产生这样的输出?
【发布时间】:2014-07-25 14:51:57
【问题描述】:

为什么这个程序会写 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] 似乎在这里造成了麻烦。

【问题讨论】:

  • 当您使用断点调试应用程序并观察值时发生了什么?
  • 调试的时候不会去构造函数让我看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 但我不知道为什么这些值。
  • 尽量不要将构造函数放在一行,以帮助调试。
  • 你有错字吗?总和([10..19])= 145

标签: c++ arrays output


【解决方案1】:

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

试图在静态类型与动态类型不同时进行指针运算是未定义的行为,因此就语言而言,任何事情都可能发生。

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

【讨论】:

  • 是的。很好的解释。这是有道理的——当像你这样的人这样说的时候,这听起来很容易。谢谢。
【解决方案2】:

问题是数组不包含指向对象的指针,而是整个对象。 因此,当您通过指向基类的指针使用 D 数组时,(正如 James 所指出的)行为是未定义的。

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

所以循环只查看前 5 个 D 对象:

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

总和是不祥的 125。

【讨论】:

  • 可能。行为是未定义的,事实上,任何事情都可能发生。如果他向 B 添加了一个虚拟析构函数(如果您正在派生,建议这样做),结果可能(并且可能会)完全不同。
  • 是的。当有虚函数并且你在循环中调用一个时,真正的乐趣就开始了。 (当然,在大多数机器上,仅将其中一种数据类型更改为double 会导致非常奇怪的结果。)
【解决方案3】:

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

【讨论】:

    【解决方案4】:

    运行以下代码,你就知道原因了

        #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;
    }
    

    【讨论】:

    • 你应该提供原因,而不是说“你会知道原因”。
    猜你喜欢
    • 2013-03-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-04-04
    • 1970-01-01
    • 2013-10-07
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多