类构造函数、析构函数、对象数组

第八章(第一部分)

A.构造函数和析构函数

一、构造函数Constructor的特征

(1) 语法SYNTAX

  1. 构造函数的函数名与类名相同;
  2. 构造函数没有返回值;
  3. 当新对象被创建时,构造函数会被自动调用。
class ClassName{
    public:
    	ClassName(Parameter List)
        {
            
        }
}

下面是几个构造函数实例:

class Playing Card{
    public:
    //构造函数,创建新的playing card
    PlayingCard(Suits is,int ir)
    {
        //函数体中的语句可以是普通函数的任意语句,也可以对类成员任意赋值、调用。
        suitValue=is;
        rankValue=ir;
    }
    ...
	private:
    	Suits suitValue;
    	int rankValue;
}

(2) 初始化器Initializer

构造函数可以使用初始化器Initializer来初始化,更加便利。

初始化器的语法是紧挨在参数列表圆括号之后一个冒号:,在函数体花括号{}之前成员+(形参),以逗号相连。

值得注意的是,初始化器只能初始化一些普通成员,有些成员是不能初始化的

举例:

class PlayingCard{
    public:
    	PlayingCard(Suits is,int ir):suitValue(is),rankValue(ir)
        {}
    ...
	private:
    	Suits suitValue;
    	int rankValue;
}

(3) 默认构造函数Default Constructor

没有参数的构造函数是默认构造函数。一个类只能有一个默认构造函数。

ClassName::ClassName()
{}

用户可以自定义构造函数,如果没有写任何自定义构造函数,那么系统就会自动生成一个空的默认构造函数。注意:如果用户自定义了一个[非默认构造函数](## 构造函数的重载Overloaded Constructors),但是没有自定义一个默认构造函数,此时系统并不会自动生成默认构造函数!!

例如一个类定义如下:

class PlayingCard{
    public:
    	PlayingCard(Suits is,int ir)//只定义了带两个参数的构造函数
        {
            suitValue=is;
            rankValue=ir;
        }
}

如果调用时:

PlayingCard cardone();//非法,无法调用默认参数
PlayingCard cardtwo;//非法,无法调用默认参数
PlayingCard cardthree(PlayingCard::Cube,5)//唯一合法创建构造函数方式

默认构造函数的特点是没有参数、没有语句。

在创建对象时,如果括号里没有参数,或者没有带括号,就会调用默认参数

(4) 构造函数的重载Overloaded Constructors

重载的构造函数相互之间以参数列表的数量和类型相互区分

class PlayingCard{
    public:
    	PlayingCard()//默认构造函数
        {
            suitValue=Diamond;
        	rankValue=1;
        }
    	PlayingCard(Suits is,int ir)//带两个参数的构造函数
        {
            suitValue=is;
            rankValue=ir;
        }
}

其相应的创建对象实例为:

PlayingCard cardOne;//调用默认构造函数
//默认构造函数调用时是不需要带括号的
PlayingCard cardThree(PlayingCard::Club,6);//调用带两个参数的构造函数

(5) 默认参数的构造函数Constructor with Default Parameters

与普通函数的默认参数规则一致,无二义性原则。

二、析构函数Destructor的特征

(1) 语法SYNTAX

  1. 函数名为“~+类名”;
  2. 没有返回值;
  3. 参数列表为空
  4. 不能被重载
  5. 无论何时,当一个对象的生命终结时,析构函数会被自动调用。
class ClassName{
    public:
    	~ClassName(){}
}

(2) 默认析构函数

如果用户没有写析构函数,系统会生成默认析构函数。

ClassName::~ClassName()
{}

三、成员的生命周期和构造函数、析构函数的调用顺序

成员的生命采取栈的形式,先被构造的先被析构,后被构造的后被析构。

例如;

#include<iostream>
using namespace std;
class Trace {
	public:
		//Constructor
		Trace(string);
		//Destructor
		~ Trace();
	private:
		string text;
};
void procedureA();
void procedureB(int x);
int main() {
	procedureA();
}

Trace::Trace(string t): text(t) {
	cout << "entering " << text << endl;
}
Trace::~Trace() {
	cout << "exiting " << text << endl;
}
void procedureA() {
	Trace dummy("procedure A");
	procedureB(7);
}
void procedureB(int x) {
	Trace dummy("procedure B");
	if (x < 5) {
		Trace aaa("true case in Procedure B");
	} else {
		Trace bbb("false cases in Procedure B");
	}
}

示例结果:
示例结果

解释:先生成了dummy(“procedure A”),然后生成了dummy(“false cases in Procedure B”),再生成了bbb(“procedure B”)。其消亡顺序与生成顺序相反。

B.对象数组

对象数组,是在内存区中开辟的用于储存一定数量的相同类的对象连续空间

建立对象数组时,分为两个步骤:

  1. 为数组本身分配内存;
  2. 为对象数组的每一个元素(对象)分配内存

(1) 语法SYNTAX:

ClassName ArrayName[const int Expression];

(2) 对象数组的初始化:

默认构造函数初始化:

如果类拥有默认构造函数成员,则可以简易地用以下形式初始化一个对象数组

PlayingCard cardArray[52];

非默认构造函数的初始化:

如果类内没有默认构造函数成员,则对象数组的创建必须以如下格式完成:

ClassName object[const int num]{
    ClassName(..., ...),//括号内参数列表
    ClassName(..., ...),
    ...
}

例如:

PlayingCard cardArray[2]={
    PlayingCard(PlayingCard::Heart,1),
    PlayingCard(PlayingCard::Club,2)
};
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Vaster4

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值