运行时多态性 - 箭头运算符访问错误的成员?
Runtime Polymorphism - Arrow operator accessing the wrong member?
我的程序中有以下 classes:
class base {
public:
int bval;
base() {
bval = 1;
}
};
class deri: public base {
int dval;
public:
deri() {
dval = 2;
}
};
还有一个函数f
,它接受指向classbase
对象的指针和它指向的数组大小:
void f(base *arr, int size) {
for(int i=0; i<size; i++, arr++){
cout << arr->bval << " ";
}
cout << endl;
}
这是主要的:
int main() {
base a[5];
f(a, 5); // first call
deri b[5];
f(b, 5); // second call
}
第一次调用的输出是 1 1 1 1 1
,这是正确的。
但是第二次调用的输出是1 2 1 2 1
,这让我很意外。对于函数 f
.
中的 for
循环的每第二次迭代,似乎 dval
的值正在代替 bval
打印
此外,如果我在 class deri
中包含另一个私有数据成员 int dval2
,则每次执行时第二次调用的输出都是 1 2 65535 1 2
(所以 65535看起来不像任何随机值)。
为什么箭头运算符表现出这种行为?
您将指针作为指向 f()
的 base
指针传递,因此指针算法不适合您的 deri
数组。
此时:for(int i=0; i<size; i++, arr++)
,只将base
的大小加到arr
,因为arr
是一个base
指针
在这种情况下,真正存储的是什么类型的对象并不重要;增加指针值时不会查看它们。
两个有用的选项:
- 使用 C++ 容器。例如。
std::vector<deri> b(5)
和 void f(const std::vector<deri> &vec)
.
- 传递一个指针数组。在这种情况下,当使用箭头运算符访问指针时,可以发生多态性。请注意,您的基础 class 需要一个
vtable
,您将通过定义和声明一个虚拟析构函数来获得它(不需要 vtable 来提供预期的输出,但出于其他几个原因)。
我的程序中有以下 classes:
class base {
public:
int bval;
base() {
bval = 1;
}
};
class deri: public base {
int dval;
public:
deri() {
dval = 2;
}
};
还有一个函数f
,它接受指向classbase
对象的指针和它指向的数组大小:
void f(base *arr, int size) {
for(int i=0; i<size; i++, arr++){
cout << arr->bval << " ";
}
cout << endl;
}
这是主要的:
int main() {
base a[5];
f(a, 5); // first call
deri b[5];
f(b, 5); // second call
}
第一次调用的输出是 1 1 1 1 1
,这是正确的。
但是第二次调用的输出是1 2 1 2 1
,这让我很意外。对于函数 f
.
for
循环的每第二次迭代,似乎 dval
的值正在代替 bval
打印
此外,如果我在 class deri
中包含另一个私有数据成员 int dval2
,则每次执行时第二次调用的输出都是 1 2 65535 1 2
(所以 65535看起来不像任何随机值)。
为什么箭头运算符表现出这种行为?
您将指针作为指向 f()
的 base
指针传递,因此指针算法不适合您的 deri
数组。
此时:for(int i=0; i<size; i++, arr++)
,只将base
的大小加到arr
,因为arr
是一个base
指针
在这种情况下,真正存储的是什么类型的对象并不重要;增加指针值时不会查看它们。
两个有用的选项:
- 使用 C++ 容器。例如。
std::vector<deri> b(5)
和void f(const std::vector<deri> &vec)
. - 传递一个指针数组。在这种情况下,当使用箭头运算符访问指针时,可以发生多态性。请注意,您的基础 class 需要一个
vtable
,您将通过定义和声明一个虚拟析构函数来获得它(不需要 vtable 来提供预期的输出,但出于其他几个原因)。