C++的类对象的sizeof值和this指针
C++的类对象的sizeof值和this指针
#include
using namespace std;
class A
{
protected:
char a;
public:
A(){ a = ‘a’;}
virtual void print();
void printa();
};
void A::print()
{
cout << “hello” << endl;
}
void A::printa()
{
// cout << a << endl;
cout << “hello a” << endl;
}
class B: virtual public A
{
};
int main()
{
A a;
B b;
A* pa = new A();
cout << “sizeof(a): “ << sizeof(a) << endl;
cout << “sizeof(b): “ << sizeof(b) << endl;
pa->printa();
pa[0].printa();
pa[1].printa();
// pa[1000000].printa(); // 段溢出造成错误
// pa[0].print(); ××××××
// pa[1].print(); ××××××
return 0;
}
首先对上述的代码进行一下解释:
类A有一个char型的成员变量a,其有两个成员函数,一个print()它是虚函数,一个printa()函数函数,它是普通的成员函数。
类B虚继承与类A
在main方法中,分别打印sizeof(a) 和sizeof(B),结果为8 和 12.
首先解释为何为8,由于它存在虚函数,因此类对象中需要保存一个虚函数表的指针,需要占据四个字节,而char类型的成员变量,占用一个字节,由于编译器存在字节对齐的问题,因此它将被对齐为四个字节,一共为八个字节。
对于B类对象,在A类对象的基础上,由于它是虚继承于A类,因此B类对象中还需要保存一个指向父类的指针,也即占用四个字节。其对象的大小为 12。
对于类A方法的调用:
指针pa调用printa()没有任何问题,输出 hello a
pa[0]调用printa():
如果 cout<< a <<endl; 注释掉,直接输出 hello a
不注释, 则正确输出 成员a 的值 a
pa[1]调用printa():
如果 cout<< a <<endl; 注释掉,直接输出 hello a
不注释, 则输出一个 随机的值。因为此时指针所引用的地址为非法地址,其中的成员变量 a并没有进行初始化,因此为随机值。
pa[1000000].printa(); 此方法的调用直接down掉了,因为它的引用已经超出了程序的段,造成了段错误。
对于×××××× 行的引用:
由于pa[0]是内存中正确的 类A的对象,不会出现问题。而 pa[0]引用了非法的,未被进行类A构造的内存,此时其this指针是非法的,因此程序down掉。
此处之所以会出现此种现象原因在于 this指针的引用:
C++编译器在编译时即加入了默认的this指针的传参,在调用成员函数时,在成员函数内部对成员数据的调用其实为 this->a ,并依此来区别不同的对象。
而对于虚函数的调用,因为要访问对象的虚函数表指针,而对于 越界的pa[1]来说此值为随机值,无法正确访问虚函数表,因此造成错误。
andy @ 2013-03-21 记
还没有评论,来说两句吧...