'类的内存分配之一' 是以指针的形式说明的.
这篇以对象的形式说明.看了侯俊杰的深入浅出MFC总结如下.
(最近会以读书笔记形式写博客,内容侯俊杰的深入浅出MFC , nehe的OpenGL教程. )
一. 还是关于父类子类的内存分配.
这个主要是之一留下的问题. 先看代码.
#include "stdafx.h" class A { public: A(){a = 2;}; int a; }; class B : public A { public: B(){a = 4;}; virtual int fun1(){return a;}; int a; }; int main(int argc, char* argv[]) { A *pa = new B(); printf("pa->a = %d\n" , pa->a); printf("A的大小: %d\n" , sizeof(A)); printf("pa地址: %x\n" , pa); printf("pa->a的地址 :%x\n" , &(pa->a));delete pa; return 0; }
运行结果如下:
之一曾说过. A *pa = new B(); 这种形式只是传递了数据内存的首地址.
上面代码中,
new B()内存分配如下.
vptr (虚函数表指针)指向B::fun1() |
A::a 父类的成员变量 a = 2 |
B::a 父类的成员变量 a = 4 |
如果传递了数据内存的首地址. 那么为什么 pa的地址和pa->a的地址一样的?
B *pb = new B();
A *pa = pb;
printf("pb地址: %x\n" , pb);
我又作了上面的操作. 暂且认为B *pb = new B();和 A *pa = pb; 等价于A
*pa = new B();.
这时pb地址为: 382c98.这下和我猜的差不多,在传递首地址的时候如果没有虚函数,
虚函数表指针是不传递的.
二.
关于类对象的内存分配.
也是先来代码.
#include "stdafx.h" class B { public: virtual void fun(){ printf("B::fun()\n"); }; }; class C : public B { public: virtual void fun(){ printf("C::fun()\n"); }; }; int main(int argc, char* argv[]) { C *pc = new C (); C _c ; _c.fun(); ((B*)(&_c))->fun(); pc->fun(); ((B)_c).fun(); return 0; }
运行结果:
那为什么最后一个是B::fun()呢...
原因:
((B)_c).fun();
调用了B的默认的拷贝构造函数. 拷贝构造函数如下:
B::B(B &_b)
{//没有成员变量.
所以为空.
}
但是注意2各方面,
第一没有拷贝构造虚函数表的指针.
第二是参数类型是引用. 是址传递, 而不是值传递.B是C的父类, 传来的参数_c的首地址.
如果有成员变量的话, 传来的还是父类的值....
所以拷贝构造函数没有覆盖虚函数表的指针.
所以还是调用B::fun();