我正在尝试实现下面的函数和类,但是 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;
}
void Derived :: foo() {
Derived arr[3];
init(arr);
指向Derived
的指针Derived*
被传递给函数init(Base *b)
。接下来发生的是,您的函数不会移动表中的 sizeof(Derived)=8
,而是移动 sizeof(Base)=4
,这会导致 的初始化code>x
数组中第一个和第二个 Derived
的成员以及第一个 Derived
的 y
成员,但不是 x
最后一个 Derived
。
Pointer arithmetic is done based on the size of the type of the
pointer
考虑这个内存布局(在 x64 上):
在派生::foo()中:
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
但在 Derived::init( Base* b) 中:
b[0].x = 0x7fffffffe310 // set arr[0].x to 0
+4 =
b[1].x = 0x7fffffffe314 // set arr[0].y to 0
+4 =
b[2].x = 0x7fffffffe318 // set arr[1].x to 0
因此,您已将 arr[0].x 设置为 0,将 arr[1].x 设置为 0,顺便将 arr[0].y 设置为 0。这不是您想要的。解决方案是将 Derived::init 更改为
void Derived::init( Derived *d) {
for( int i = 0; i < 3; ++i) {
d[i].x = 0;
}
}
或者更好,遵循更通用的编程原则:
template < size_t N>
void Derived::init( Derived (&d)[N] ) {
for( int i = 0; i < N; ++i) {
d[i].x = 0;
}
}