现在的位置: 首页 > 综合 > 正文

C++类的内存分配之二

2017年12月28日 ⁄ 综合 ⁄ 共 1224字 ⁄ 字号 评论关闭

'类的内存分配之一' 是以指针的形式说明的.

这篇以对象的形式说明.看了侯俊杰的深入浅出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();





抱歉!评论已关闭.