C++学习笔记4——封装篇(下)

学习教程:https://www.imooc.com/learn/405

对象数组

举例:

Coordinate coord[3]; //在栈上实例化一个对象数组
Coordinate *p = new Coordinate[3]; //在堆中实例化一个对象数组,这里是[3],会调用3次构造函数

数组被实例化完成之后,每一个元素都可以访问其各自的数据成员

//在栈上实例化的:
coord[1].m_iX = 10;
//在堆上实例化的:
p[0].m_iY = 20; //或者:p->m_iY = 20;

在堆中实例化的,用完之后要销毁:

delete []p; //销毁的过程中会调用三次析构函数
p = NULL;

在这里插入图片描述
编码示例:
Coordinate.h

class Coordinate
{
public:
	Coordinate();
	~Coordinate();
public:
	int m_iX;
	int m_iY;
};

Coordinate.cpp

#include <iostream>
#include "Coordinate.h"
using namespace std;

Coordinate::Coordinate()
{
	cout << "Coordinate" << endl;
}

Coordinate::~Coordinate()
{
	cout << "~Coordinate" << endl;
}

demo.cpp

#include <iostream>
#include "Coordinate.h"
using namespace std;

int main()
{
	Coordinate coor[3]; //从栈上实例化数组
	coor[0].m_iX = 1; //赋值
	coor[0].m_iY = 2;
	coor[1].m_iX = 11;
	coor[1].m_iY = 22;
	coor[2].m_iX = 111;
	coor[2].m_iY = 222;

	Coordinate *p = new Coordinate[3];
	//以下用两种方式访问数组第一个元素
	p->m_iX = 3;
	p[0].m_iY = 4;

	p++; //此时p指向数组的第二个元素
	p->m_iX = 5; //此时访问到的是数组的第二个元素
	p[0].m_iY = 6; //此时这样子访问的也是数组的第二个元素,且不能再用这个方式访问数组的第一个元素,[]中不能是复数

	p[1].m_iX = 7; //此时访问的是数组的第三个元素
	p++; //此时p指向数组的第三个元素
	p->m_iY = 8; //此时是给数组的第三个元素的成员赋值

	//以下遍历数组:
	int i;
	for (i = 0; i < 3; i++)
	{ 
		cout << "coor_x" << coor[i].m_iX << endl;
		cout << "coor_y" << coor[i].m_iY << endl;
	}

	for (i =0; i < 3; i++)
	{
		cout << "p_x" << p->m_iX << endl; //因为前面已经做了两次p++,现在p已经指向数组最后一个元素
		cout << "p_y" << p->m_iY << endl;
		p--; //从后往前遍历
	}
	p++; //上面的for循环,做最后一次遍历(即遍历第一个元素)后,又做了一次p--,此时p指向数组第一个元素的前一个。这样子是不可以直接delete 的,要让p指回数组第一个元素
	delete []p;
	p = NULL;

	return 0;
}

对象成员

举例:
要实现描述一条线段,需要有坐标点A、B,和线段。定义两个类,一个坐标类,有A、B两个对象,定义一个线段类
实例化对象时,先实例化点A,再实例化点B,再实例化线段,销毁顺序为实例化顺序的逆序。

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
编码示例1:
Coordinate.h

class Coordinate
{
public:
	Coordinate();
	~Coordinate();
	void setX(int x);
	int getX();
	void setY(int y);
	int getY();
private:
	int m_iX;
	int m_iY;
};

Coordinate.cpp

#include <iostream>
#include "Coordinate.h"
using namespace std;

Coordinate::Coordinate()
{
	cout << "Coordinate" << endl;
}

Coordinate::~Coordinate()
{
	cout << "~Coordinate" << endl;
}

void Coordinate::setX(int x)
{
	m_iX = x;
}

int Coordinate::getX()
{
	return m_iX;
}

void Coordinate::setY(int y)
{
	m_iY = y;
}

int Coordinate::getY()
{
	return m_iY;
}

Line.h

#include "Coordinate.h"

class Line
{
public:
	Line();
	~Line();
	void setA(int x, int y); //线段A
	void setB(int x, int y); //线段B
	void printinfo();
private:
	Coordinate m_coorA;
	Coordinate m_coorB;
};

Line.cpp

#include <iostream>
#include "Line.h"
using namespace std;

Line::Line()
{
	cout << "Line()" << endl;
}

Line::~Line()
{
	cout << "~Line()" << endl;
}

void Line::setA(int x, int y)
{
	m_coorA.setX(x);
	m_coorA.setY(y);
}

void Line::setB(int x, int y)
{
	m_coorB.setX(x);
	m_coorB.setY(y);
}

void Line::printinfo()
{
	cout << "(" << m_coorA.getX() << "," << m_coorA.getY() << ")" << endl;
	cout << "(" << m_coorB.getX() << "," << m_coorB.getY() << ")" << endl;
}

demo.cpp

#include <iostream>
#include "Coordinate.h"
#include "Line.h"
using namespace std;

int main()
{
	Line *p = new Line();
	delete p;
	p = NULL;
	return 0;
}

在这里插入图片描述
先调用两次坐标类的构造函数,再调用线段类的构造函数,说明先创建两个坐标类的对象,即A点和B点,然后再调用线段的对象(该对象是在A点和B点初始化完成之后才创建的)。
销毁时,先调用线段类的析构函数,再调用坐标类的析构函数,与创建对象的顺序相反。

示例2:
Coordinate.h

class Coordinate
{
public:
	Coordinate(int x, int y);
	~Coordinate();
	void setX(int x);
	int getX();
	void setY(int y);
	int getY();
private:
	int m_iX;
	int m_iY;
};

Coordinate.cpp

#include <iostream>
#include "Coordinate.h"
using namespace std;

Coordinate::Coordinate(int x, int y)
{
	m_iX = x;
	m_iY = y;
	cout << "Coordinate  " <<  m_iX << " , " << m_iY << endl; // 打印X和Y是为了根据输出判断先调用A点的构造函数还是先调用B点的构造函数(以知道先实例化A还是B)
}

Coordinate::~Coordinate()
{
	cout << "~Coordinate" << m_iX << " , " << m_iY << endl;// 打印X和Y是为了根据输出判断先调用A点的析构函数还是先调用B点的析构函数
}

void Coordinate::setX(int x)
{
	m_iX = x;
}

int Coordinate::getX()
{
	return m_iX;
}

void Coordinate::setY(int y)
{
	m_iY = y;
}

int Coordinate::getY()
{
	return m_iY;
}

Line.h

class Line
{
public:
	Line(int x1,int y1, int x2, int y2);
	~Line();
	void setA(int x, int y); //线段A
	void setB(int x, int y); //线段B
	void printinfo();
private:
	Coordinate m_coorA;
	Coordinate m_coorB;
};

Line.cpp

#include <iostream>
#include "Line.h"
using namespace std;

Line::Line(int x1, int y1, int x2, int y2):m_coorA(x1,y1),m_coorB(x2,y2) //用了初始化列表
{
	cout << "Line()" << endl;
}

Line::~Line()
{
	cout << "~Line()" << endl;
}

void Line::setA(int x, int y)
{
	m_coorA.setX(x);
	m_coorA.setY(y);
}

void Line::setB(int x, int y)
{
	m_coorB.setX(x);
	m_coorB.setY(y);
}

void Line::printinfo()
{
	cout << "(" << m_coorA.getX() << "," << m_coorA.getY() << ")" << endl;
	cout << "(" << m_coorB.getX() << "," << m_coorB.getY() << ")" << endl;
}

demo.cpp

#include <iostream>
#include "Coordinate.h"
#include "Line.h"
using namespace std;

int main()
{
	Line *p = new Line(1,2,3,4);
	p->printinfo();
	delete p;
	p = NULL;
	return 0;
}

在这里插入图片描述
先实例化A点,再实例化B点,再实例化线段。销毁时,先销毁线段,再销毁B点,最后销毁A点

由示例可知,若坐标类有一个默认构造函数(不带参数的构造函数),即示例1 Coordinate.h中Coordinate();,就可以在实例化线段对象时,不使用初始化列表(Line.cpp中即Line::Line(int x1, int y1, int x2, int y2):m_coorA(x1,y1),m_coorB(x2,y2) //用了初始化列表 不用初始化列表也是可以的)但如示例2 Coordinate.h中Coordinate(int x, int y);,构造函数要求要有参数传入,在实例化线段类的时候,就必须使用初始化列表将相应的值传给坐标类

实例化对象A时,如果对象A有对象成员B,那么先执行对象B的构造函数,再执行A的构造函数。

实例化对象A时,如果对象A有对象成员B,那么先执行对象B的构造函数,再执行A的构造函数。

如果对象A中有对象成员B,那么销毁对象A时,先执行对象A的析构函数,再执行B的析构函数。

如果对象A中有对象成员B,对象B没有默认构造函数,那么对象A必须在初始化列表中初始化对象B。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值