C++中子类的数组不能用父类指针来表示

假设我们有一个父类A,一个子类B,如果我们创建一个B的数组,我们能这样用吗?

A* barray = new B[10];

写段代码在Visual Studio中来试试吧:)

 

 1 #include <iostream>
 2 #include <assert.h>
 3 
 4 using namespace std;
 5 class B;
 6 class A
 7 {
 8 public:
 9     A();
10     ~A();
11     int aa;
12 };
13 
14 class B:public A
15 {
16 public:
17     B();
18     ~B();
19     int bb;
20 };
21 
22 A::A()
23 {
24     cout<<"A"<<" ";
25     aa=1;
26 }
27 
28 A::~A()
29 {
30     cout<<"~A"<<" ";
31     aa=-1;
32 }
33 
34 B::B()
35 {
36     cout<<"B"<<" ";
37     bb=2;
38 }
39 
40 B::~B()
41 {
42     cout<<"~B"<<" ";
43 
44     bb=-2;
45 }
46 
47 int main(int argc, char* argv[])
48 {
49     cout<<"size of A: "<<sizeof(A)<<endl;
50     cout<<"size of B: "<<sizeof(B)<<endl;
51     A* aarray = new B[10];
52 
53     cout<<endl<<endl<<"aa value of A* is:"<<endl;
54     for (int i = 0; i < 10; i++)
55     {
56         cout<<aarray[i].aa<<", ";
57     }
58     cout<<endl;
59 
60     B* baaray = (B*)aarray;
61     cout<<endl<<"aa value of B* is:"<<endl;
62     for (int i = 0; i < 10; i++)
63     {
64         cout<<baaray[i].aa<<", ";
65     }
66     cout<<endl<<endl;
67 
68     delete[] aarray;
69     cout<<endl<<endl<<"After delete[]"<<endl;
70 
71     cout<<endl<<"aa value of A* is:"<<endl;
72     for (int i = 0; i < 10; i++)
73     {
74         cout<<aarray[i].aa<<", ";
75     }
76     cout<<endl;
77     baaray = (B*)aarray;
78     cout<<endl<<"aa value of B* is:"<<endl;
79     for (int i = 0; i < 10; i++)
80     {
81         cout<<baaray[i].aa<<", ";
82     }
83     return 0;
84 }

 

我们可以看到输出的结果是:

size of A: 4
size of B: 8
A B A B A B A B A B A B A B A B A B A B

aa value of A* is:
1, 2, 1, 2, 1, 2, 1, 2, 1, 2,

aa value of B* is:
1, 1, 1, 1, 1, 1, 1, 1, 1, 1,

~A ~A ~A ~A ~A ~A ~A ~A ~A ~A

After delete[]

aa value of A* is:
4408224, -1, -1, -1, -1, -1, -1, -1, -1, -1,

aa value of B* is:
4408224, -1, -1, -1, -1, 1, 1, 1, 1, 1, 

说明尽管我们创建时用的是new B,但是因为声明的是A*,所以被认为是一个A的数组,按照A的大小来操作,所以可以看到成员变量aa的值是不对的。而且最后析构的时候只调用了A的析构函数,说明这个数组在delete的时候也是有问题的。

 

如果我们把A的析构函数加上virtual,可以得到如下的结果:

size of A: 8
size of B: 12
A B A B A B A B A B A B A B A B A B A B

aa value of A* is:
1, 668240, 2, 1, 668240, 2, 1, 668240, 2, 1,

aa value of B* is:
1, 1, 1, 1, 1, 1, 1, 1, 1, 1,

~B ~A ~B ~A ~B ~A ~B ~A ~B ~A ~B ~A ~B ~A ~B ~A ~B ~A ~B ~A

After delete[]

aa value of A* is:
-1, 668248, -2, -1, 668248, -2, -1, 668248, -2, -1,

aa value of B* is:
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1,

说明只要我们加上virtual,在delete的时候编译器是知道怎么delete的。

 

但是这并不是C++标准中制定的,不同的编译器会有不同的结果,比如如果把带virtual的代码放在g++中,会得到如下的结果:

size of A: 8
size of B: 12
A B A B A B A B A B A B A B A B A B A B 

aa value of A* is:
1, 134540944, 2, 1, 134540944, 2, 1, 134540944, 2, 1, 

aa value of B* is:
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 


Segmentation fault

 

所以,C++中子类的数组不能用父类指针来表示。

posted on 2012-12-03 20:40  fresky  阅读(584)  评论(0编辑  收藏  举报

导航