ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

继承下的构造函数与析构函数

2021-12-08 22:32:44  阅读:139  来源: 互联网

标签:leng 函数 int 与析构 基类 MyArray 派生类 构造函数


●掌握派生类的声明方法和派生类构造函数的定义方法
●掌握不同方式下,构造函数与析构函数的执行顺序与构造规则

派生类的声明与构造函数的定义

1、派生类的声明

Class 派生类:[继承方式] 基类名{

        派生类新增的数据成员和成员函数

};

如果不显式地给出继承方式关键字,系统默认为私有继承(private)。类的继承方式指定了派生类成员以及类外对象对于从基类继承来的成员的访问权限。

派生类的工作包括三部分:

(1)派生类从基类接收成员。

(2)调整从基类接受来的成员。

(3)在派生类中增加新的成员。

2、构造函数的定义

派生类名(参数总表):基类名(参数表){

派生类新增数据成员的初始化语句

}

冒号后面的部分是要调用的基类构造函数及其参数。

(1)可以将派生类构造函数定义在类的外部,而在类体内只写该函数的声明。(在类中声明派生类构造函数时,不包括基类构造函数名及其参数表,只在类外定义构造函数时才将它列出)

(2)若基类使用默认构造函数或不带参数的构造函数,则在派生类中定义构造函数时,可略去“:基类构造函数名(参数表)”,此时若派生类不需要构造函数,则可不定义派生类构造函数。

(3)当基类构造函数不带参数时,派生类不一定需要定义构造函数,然而当基类的构造函数哪怕只带有一个参数,它所有的派生类都必须定义构造函数,甚至所定义的派生类构造函数的函数体可能为空,仅仅起参数的传递作用。

构造函数与析构函数的执行顺序与构造规则

使用以下代码,观察其执行结果。

#include<iostream>
using namespace std;

class MyArray {
public:
	MyArray(int length);
	~MyArray();
	void Input();
	void Display(string);
protected:
	int* alist;
	int length;
};

MyArray::MyArray(int leng) {
	if (leng <= 0) {
		cout << "error length";
		exit(1);
	}


	alist = new int[length];
	length = leng;
	if (alist == NULL) {
		cout << "assign failure";
		exit(1);
	}
	cout << "MyArray类对象已创建!" << endl;
}

MyArray::~MyArray() {
	delete[]alist;
	cout << "MyArray类对象已撤销!" << endl;
}

void MyArray::Display(string str) {
	int i;
	int* p = alist;
	cout << str << length << "个整数:";
	for (i = 0; i < length; i++, p++)
		cout << *p << " ";
	cout << endl;
}

void MyArray::Input() {
	cout << "请从键盘输入" << length << "个整数:";
	int i;
	int* p = alist;
	for (i = 0; i < length; i++, p++)
		cin >> *p;
}

int main() {
	MyArray a(5);
	a.Input();
	a.Display("显示已经输入的");
	return 0;
}

其结果是

这是典型的内存溢出错误,常在内存的delete处发生。这是因为在新建立alist内存空间时,有两句语句的顺序出现错误,length = leng; alist = new int[length];,这时候length的数字是个随机数,在最后delete释放的时候,其会出现错误的情况。

因此先保证用new分配的内存空间足够,就不会导致这个问题,因此在两条语句互换一下位置便能够使程序正常运行。其析构函数能够被正常的执行了。

●声明一个SortArray继承类MyArray,在该类中定义一个函数,具有将输入的整数从小到大进行排序的功能

代码如下:

(1)冒泡排序


#include<iostream>
using namespace std;

class MyArray {
public:
	MyArray(int length);
	~MyArray();
	void Input();
	void Display(string);
protected:
	int* alist;
	int length;
};

MyArray::MyArray(int leng) {
	if (leng <= 0) {
		cout << "error length";
		exit(1);
	}
	length = leng;
	alist = new int[length];
	if (alist == NULL) {
		cout << "assign failure";
		exit(1);
	}
	cout << "MyArray类对象已创建!" << endl;
}

MyArray::~MyArray() {
	delete[]alist;
	cout << "MyArray类对象已撤销!" << endl;
}

void MyArray::Display(string str) {
	int i;
	int* p = alist;
	cout << str << length << "个整数:";
	for (i = 0; i < length; i++, p++)
		cout << *p << " ";
	cout << endl;
}

void MyArray::Input() {
	cout << "请从键盘输入" << length << "个整数:";
	int i;
	int* p = alist;
	for (i = 0; i < length; i++, p++)
		cin >> *p;
}

class SortArray :public MyArray {
public:
	SortArray(int leng);
	~SortArray();
	void rank();
};

SortArray::SortArray(int leng):MyArray(leng) {
	cout << "SortArray类对象已经创建!" << endl;
}

SortArray::~SortArray() {
	cout << "SortArray类对象已撤销!" << endl;
}

void SortArray::rank() {
	Display("显示排序之前");
	int* p = alist;
	for (int i = 0; i < length; i++) {
		for (int j = i + 1; j < length; j++)
			if (*(p + i) > *(p + j)) {
				int temp = *(p + i);
				*(p + i) = *(p + j);
				*(p + j) = temp;
			}
	}
	Display("显示排序之后");
}

int main() {
	SortArray a(5);
	a.Input();
	a.Display("显示已经输入的");
	a.rank();
	return 0;
}

其运行结果取下:

由这个代码,我们可以得出在派生类中,构造函数与析构函数的执行顺序。通常情况下,当创建派生类对象时,首先执行基类的构造函数,随后再执行派生类的构造函数;当撤销派生类对象时,则先执行派生类的析构函数,随后再执行基类的析构函数。 

(2)基数排序


#include<iostream>
using namespace std;

class MyArray {
public:
	MyArray(int length);
	~MyArray();
	void Input();
	void Display(string);
protected:
	int* alist;
	int length;
};

MyArray::MyArray(int leng) {
	if (leng <= 0) {
		cout << "error length";
		exit(1);
	}
	length = leng;
	alist = new int[length];
	if (alist == NULL) {
		cout << "assign failure";
		exit(1);
	}
	cout << "MyArray类对象已创建!" << endl;
}

MyArray::~MyArray() {
	delete[]alist;
	cout << "MyArray类对象已撤销!" << endl;
}

void MyArray::Display(string str) {
	int i;
	int* p = alist;
	cout << str << length << "个整数:";
	for (i = 0; i < length; i++, p++)
		cout << *p << " ";
	cout << endl;
}

void MyArray::Input() {
	cout << "请从键盘输入" << length << "个整数:";
	int i;
	int* p = alist;
	for (i = 0; i < length; i++, p++)
		cin >> *p;
}

class SortArray :public MyArray {
public:
	SortArray(int leng);
	~SortArray();
	void rank();
};

SortArray::SortArray(int leng):MyArray(leng) {
	cout << "SortArray类对象已经创建!" << endl;
}

SortArray::~SortArray() {
	cout << "SortArray类对象已撤销!" << endl;
}

int maxbit(int* a, int n) { //找出数据中在大位数是几位

	int d = 1; //保存最大的位数
	int p = 10;
	for (int i = 0; i < n; ++i)
	{
		while (*(a + i) >= p)
		{
			p *= 10;
			++d;
		}
	}
	return d;
}

void radixsort(int *a,int n) {//基数排序
	int d = maxbit(a, n);
	int *temp = new int[n];
	int* count = new int[10]; //计数器
	int i, j, k;
	int radix = 1;
	for (i = 0; i <= d; i++) {  //进行d次排序
		for (j = 0; j < 10; j++)
			count[j] = 0; //每次分配前清空计数器
		for (j = 0; j < n; j++) {
			k = (*(a+j) / radix) % 10; //统计每个桶中的记录数
			count[k]++;
		}
		for (j = 1; j < 10; j++)
			count[j] = count[j - 1] + count[j];//将temp中的位置依次分配给每个桶
		for (j = n - 1; j >= 0; j--) {//将所有桶中记录依次收集到temp
			k = (*(a + j) / radix) % 10;
			temp[count[k] - 1] = *(a + j);
			count[k]--;
		}
		for (j = 0; j < n; j++)//将临时数组的内容复制到*a中
			*(a + j) = temp[j];
		radix = radix * 10;
	}
	delete[]temp;
	delete[]count;
	cout << "基数排序后的结果" << n << "个整数:";
	for (int i = 0; i <n; i++, a++)
		cout << *a << " ";
	cout << endl;
}

void SortArray::rank() {
	Display("显示排序之前");
	int* p = alist;
	radixsort(p, length);
}


int main() {
	SortArray a(5);
	a.Input();
	a.Display("显示已经输入的");
	a.rank();
	return 0;
}

这时输出的结果为:

        基数排序是一种非比较型整数排序算法,其原理是将整数按位数切割成不同的数字,然后按每个位数分别比较。由于整数也可以表达字符串(比如名字或日期)和特定格式的浮点数,所以基数排序也不是只能使用于整数。 其不能用作负数。

其原理为,先找到这一串数列的最大位数是几位,在按照个位排序,十位排序,百位排序,最后实实现了顺序。原理如下图:

实验总结 

(1)在写派生类的时候,要注意继承方式对派生类访问基类中的数据的规则影响。

(2)在声明派生类的构造函数,需要掌握其声明规则,哪些时候需要“:基类构造函数名(参数表)”等这些要区分清楚。

(3)在排序的时候,可以多选择几种排序方法,可以多尝试。

(4)在用new分配内存空间的时候,要注意其分配的空间是否够用,会不会导致溢出。

标签:leng,函数,int,与析构,基类,MyArray,派生类,构造函数
来源: https://blog.csdn.net/Desire365/article/details/121786043

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有