c++3.5子对象和堆对象

3.5.1子对象

1.子对象的声明

一个对象作为另一个类的成员时,该对象称为类的子对象。子对象实际是某个类的数据成员。

2.子对象的初始化

为初始化子对象,X的构造函数要调用这些对象成员所在类的构造函数,于是X类的构造函数中就应包含数据成员初始化列表,用来给子对象初始化。

成员初始化列表中的选项可以是对子对象进行初始化的,也可以是对该类其他数据成员初始化的,其中的参数表给出为调用相应成员所在类的构造函数时应提供的参数。

对子对象的构造函数的调用顺序取决于这些子对象在类中说明的顺序(与它们在成员初始化列表中给出的顺序无关)

当建立X类的对象时,先调用子对象的构造函数,初始化子对象,然后才执行X类的构造函数,初始化X类中的其他成员。

析构函数的调用顺序与构造函数相反。

来个例子。(前面的概念感觉干巴巴的,还记不住)

#include<iostream>
using namespace std;
class Part
{
public:
	Part();
	Part(int x);
	~Part();
private:
	int val;
};
Part::Part ()//默认构造函数
{
	val=0;
	cout<<"Default constructor of Part"<<endl;
}
Part::Part(int x)
{
	val=x;
	cout<<"Constructor of part"<<","<<val<<endl;
}
Part::~Part ()
{
	cout<<"Destructor of Part"<<","<<val<<endl;
}
class Whole
{
public:
	Whole(int i);
	Whole(){};
	~Whole();
private:
	Part p1;//对子对象的构造函数的调用顺序起决定作用
	Part p2;
};
Whole::Whole (int i):p1(),p2(i)//对子对象初始化,与子对象的构造函数调用顺序无关
{
	cout<<"Constructor of Whole"<<endl;
}
Whole::~Whole ()
{
	cout<<"Constructor of Whole"<<endl;
}
int main()
{
	Whole w(3);
	return 0;
}

结果:

Default constructor of Part
Constructor of part,3
Constructor of Whole
Constructor of Whole
Destructor of Part,3
Destructor of Part,0

Whole类的默认构造函数没有给出成员初始化列表,这表明子对象将使用默认构造函数进行初始化。

int main()
{
Whole w;//调用默认构造函数
return 0;
}

结果:

Default constructor of Part
Default constructor of Part
Constructor of Whole
Destructor of Part,0
Destructor of Part,0

如果Whole类中还有其他数据成员,其初始化也可通过成员初始化列表进行

class Whole
{
public:
	Whole(int i);
	Whole(){};
	~Whole();
private:
	Part p1;
	Part p2;
	int data;
};
//为了初始化数据成员data,这时该构造函数也可以定义成如下格式
Whole::Whole(int i,j):p1(),p2(i),data(j)
{
}

3.5.2堆对象

堆对象是在程序运行时根据需要随时可以被创建或删除的对象。

在虚拟的程序空间中存在一些空闲存储单元,这些空闲存储单元组成的所谓的堆。

创建或删除堆对象分别使用new和delete

1.使用new创建堆对象

使用语法

new<类型说明符><初始值列表>

new 的返回值是一个指针,使用该运算符给某对象分配一个地址值,由<类型说明符>来给定对象的类型。

在使用该运算符创建对象时,系统自动调用该类的构造函数,并根据<初始值列表>中的初始值的个数来选择对应参数个数的构造函数。

举个例子:

HeapObjectClass *pa;
pa=new HeapObjectClass(3,7);

pa是一个指向类HeapObjectClass的对象指针,new创建一个类HeapObjectClass的对象,将它的地址值赋给pa,并对该对象进行初始化,调用具有两个参数的构造函数,初始值为3和7.

2.delete删除堆对象

它是专门用来释放new所创建的对象的。
语法:

delete<指针名>

因为堆是有限的,如果堆中没有足够的自由空间以满足内存的需要时,那么此需要失败,并且new返回一个空指针。因此,必须在使用new生成的指针之前进行检查。

来,举个例子吧

int main()
{
Heapclass *pa1,*pa2;
pa1=new Heapclass(4);//分配空间
pa2=new Heapclass;//分配空间
if(pa1||pa2)//检查空间
{
	cout<<"Out of Memory!"<<endl;
	return 0;
}
cout<<"Exit main"<<endl;
delete pa1;
delete pa2;
return 0;
}

3.使用new[]创建对象数组

new<类型说明符>[<算数表达式>]
比如:

ObjectClass *ptr;
ptr=new ObjectClass[15];

该数组的每个元素都是ObjectClass的对象,ptr是指向对象数组首元素的指针

4.使用delete[]删除对象数组

delete[ ]指针名
比如:

delete[] ptr;

注意啊

  • delete[]必须用于由new[]返回的指针
  • 对一个指针只能使用一次delete[]
  • 指针名前只能用一对方括号,不用管所释放的数组的维数,而且方括号内不能写任何东西
  • 该运算符也适用于空指针

最后的话

堆空间给程序运行带来了极大的自由度。
但是管理堆区是一件十分复杂的工作,频繁的分配和释放不同大小的堆空间将会产生堆内碎块。(额,为啥会产生呢?)

使用堆空间往往是由于:

  • 直到运行时才能知道需要多少对象空间
  • 不知道对象的生命周期
  • 直到运行时才知道一个对象需要多少内存空间。

以上内容全部出自教材啊

  • 2
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值