派生类有些麻烦

时间:2014-03-10 17:15:59

标签: c++ arrays class oop object

我正在尝试实现下面的函数和类,但是arr [i] .x的输出是错误的。我正确得到arr [0] .x = 0和arr [1] .x = 0,但arr [2] .x不返回0.任何想法为什么?

class Base {
public:
  int x;
};

class Derived : public Base {
public:
int y;
void init(Base *b);
void foo();
};

void Derived :: init(Base *b) {
  for( int i = 0; i < 3; ++i) {
    b[i].x = 0;
  }
}

void Derived :: foo() { 
  Derived arr[3];
  init(arr);
  for( int i = 0; i < 3; ++i) {
  cout<<"b["<<i<<"] "<<arr[i].x;
  }
}


int main()
{
    Derived der;
    der.foo();
    return 0;
}

4 个答案:

答案 0 :(得分:2)

void Derived :: foo() { 
    Derived arr[3];
    init(arr);

指向DerivedDerived*的指针将传递给函数init(Base *b)。接下来会发生什么,而不是按表格中的sizeof(Derived)=8移动,您的函数将移动sizeof(Base)=4,导致数组中第一个和第二个x的{​​{1}}成员初始化以及Derived的{​​{1}},但不是最后y的{​​{1}}。

  

指针算法是根据类型的大小完成的   指针

考虑这个内存布局(在x64上):

Derived :: foo()中的

Derived

但在Derived :: init(Base * b)中:

x

因此,您已将arr [0] .x设置为0,将arr [1] .x设置为0,并将arr [0] .y设置为0.这不是您想要的。解决方案是将Derived :: init更改为

Derived

甚至更好,遵循更通用的编程原则:

Derived arr[3];

0x7fffffffe310  // 1st Derived, also address of arr[0].x
+8 = 
0x7fffffffe318  // 2nd Derived, also address of arr[1].x
+8 = 
0x7fffffffe320  // 3rd Derived, also address of arr[2].x

答案 1 :(得分:1)

原因是init()不知道你实际上是在传递Derived *而不是Base *。

所以init()函数中的循环,假设为了到达数组中的下一个条目,sizeof(Base)被添加到指针,而不是sizeof(Derived)。

答案 2 :(得分:0)

变化

cout<<"b["<<i<<"] "<<arr[i].x;

cout<<"b["<<i<<"] "<<arr[i].x<<endl;

然后你会看到正确的号码。

endl的额外功能是刷新与此流关联的缓冲区。如果你不这样做,它有时会输出一些随机数。

答案 3 :(得分:-1)

对于一个你通过值而不是通过引用将指针(* b)传递给函数init()。

Here's a nice explanation as to why that matters他们解释得比我可能更好

尝试使init函数看起来像这样

init(Base& *b)

看看会发生什么。