下列程序的输出结果是什么?
#include "stdafx.h" #include <iostream> using namespace std; class A { public: int _a; A() { _a = 1; } void print() { cout << _a << endl; } }; class B : public A { public: int _a; B() { _a = 2; } }; int _tmain(int argc, _TCHAR* argv[]) { B b; b.print(); cout<<b._a<<endl; system("pause"); return 0; }
结果:
一开始很容易会误以为是22
首先,我们来看一下什么时候,输出会是22呢?
只要把B中_a定义这一行注释掉,就会是22了,至于为什么,对于一开始以为答案是22的朋友,显而易见。
那么为什么题中会是12呢?
我们可以将A,B两个类的大小(对象大小)输出:
int _tmain(int argc, _TCHAR* argv[]) { cout<<sizeof(A)<<endl; cout<<sizeof(B)<<endl; B b; b.print(); cout<<b._a<<endl; system("pause"); return 0; }
可以看到,B的大小是A的2倍,这是因为在B中有两个int型变量:
A::_a
B::_a
如果我们在开始的地方加上断点调试就会发现,在B类实例初始化的时候,首先会把A::_a赋值为1,然后把B::_a赋值为2,而当执行print的时候,实际上是进入A中:
所以输出的当然是A::_a,实际上,如果把B中,定义_a的一行去掉,依然输出的是A::_a,如果想要输出B::_a,只有在B中增加print(),才行,而且此时输出的就会是22。
还有一题:
这个是从http://bbs.csdn.net/topics/330161711这里copy的,不过讲的挺好的
struct S { int i; int *p; }; main() { S s; int *p = &s.i; p[0] = 4; //把i的值改为4 p[1] = 3;//这个地方越界写了,把保存在int i下面的指针int* p的值给写为3了 s.p = p; //又把这个结构体s中指针p的值赋为上面int i的地址 s.p[1] = 1;//i下面的指针指向i的地址,现在把自身修改为1了 s.p[0] = 2;//再访问内容为1的指针所指空间就出错了,这行崩溃了 }