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++中子类的数组不能用父类指针来表示。