IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> C++知识库 -> C++学习杂记(三) -> 正文阅读

[C++知识库]C++学习杂记(三)


主要学习内容

一、C++析构函数

  1. 析构函数的特征
    (1)没有返回值
    (2)函数名是在类名前面加~符号。
    (3)和构造函数一样,也是一种特殊的成员函数,不需要程序员显示调用。
    (4)析构函数没有参数,不能被重载,因此一个类只能有一个析构函数;如果用户没有定义,编译器会自动生成一个默认的析构函数。
    注意:
    a.析构函数一般是在销毁对象时自动调用的,比如释放分配的内存、关闭打开的文件。
    b. 析构函数唯一的作用就是给删除的对象后释放已经分配的内存。
#include <iostream>
using namespace std;
//定义一个模拟变长数组的类
class Demo{
//成员函数
public:
	//一般最先写构造函数
	Demo(int len);
	~Demo(); //析构函数,注意函数名为~类名,无形参无返回值
	void input(); //从控制台获取数组元素
	void show(); //打印数组
private:
	//成员变量
	const int  m_len; //数组的长度,用const修饰,表明数组的长度m_len不可修改,只能用初始化列表进行赋值。
	int *m_arr; //数组指针
	int *m_p; //指向数组中的第i个元素的指针

	int* parri(int i); //获取第i个元素的指针,返回值是一个指针
}; //类定义结束

//类的成员函数定义
//m_len使用了const修饰,只能使用初始化列表给构造函数形参赋值
Demo::Demo(int len):m_len(len){
	//在堆中给数组分配内存
	if(len > 0)
	{
		m_arr = new int[len];
	}
	else
	{
		m_arr = NULL;
	}
}
//通过new分配的内存,一般在不使用后,需要释放内存,可以通过析构函数
Demo::~Demo(){
	delete[] m_arr; //释放内存
}
int* Demo::parri(int i){
	if(!m_arr || i < 0 || i >= m_len)
	{
		return NULL;
	}
	else
	{
		return m_arr + i;
	}
}

//获取控制台的输入作为数组的元素
void Demo::input(){
	for(int i = 0; m_p = parri(i); i++)
	{
		cin>>*parri(i);
	}
}

void Demo::show(){
	for(int i = 0; m_p = parri(i); i++)
	{
		if(i == m_len -1)
		{
			cout<<*parri(i)<<endl;
		}
		else
		{
			cout<<*parri(i)<<",";
		}
	}
}

//主函数
int main()
{
	//输入一个含有n个元素的数组
	int n;
	cout<<"请输入数组的长度:";
	cin>>n;

	//调用构造函数在堆上创建对象
	Demo *parr = new Demo(n);
	//输入数组元素
	cout<<"Input "<<"n"<<"number:";
	parr->input();

	//输出数组元素
	cout<<"数组的元素有:";
	parr->show();

	//删除对象,也就是该数组
	delete parr;
	return 0;

}

输出结果:
在这里插入图片描述
注意:
a.在函数内部创建的对象是局部对象,它和局部变量类似,位于栈区,函数执行结束时会调用这些对象的析构函数。
b. new 创建的对象位于堆区,通过 delete 删除时才会调用析构函数;如果没有 delete,析构函数就不会被执行。

二、C++中的对象数组

对象数组:就是数组的每个元素都是一个对象。
既然是对象,那么数组中的每个元素都需要用构造函数进行初始化。具体如何调用哪个构造函数,看下面的示例:

#include <iostream>
using namespace std;

class Demo{
public:
	//无参构造函数
	Demo(){
		cout<<"called func1"<<endl;
	}
	//带参数的构造函数2
	Demo(int n){
		cout<<"called func2"<<endl;
	}
};

int main()
{
	cout<<"step1"<<endl;
	Demo arr[2]; //调用func1,原因是无参数

	cout<<"step2"<<endl;
	Demo arr2[2]={3,6}; //都是调用func2,两个对象元素,两个初始化的值。

	cout<<"step3"<<endl;
	Demo arr3[2] = {4};//第一个元素是调func2,参数为4;第二个元素调func1,无参数

	cout<<"step4"<<endl;
	Demo *arr4 = new Demo[2]; //无参数,调func1
	delete[] arr4;

	return 0;
}

输出结果:
在这里插入图片描述

三、C++中的成员对象

成员对象:一个类的成员变量如果是另一个类的对象,就称之为“成员对象”。
包含成员对象的类叫封闭类(enclosed class)。

#include <iostream>
using namespace std;

class Type{
public:
	//构造函数
	Type(int year, int page):m_year(year),m_page(page){};
	//成员函数
	void show() const;
private:
	int m_year;
	int m_page;
};

//Book类内部含有一个类,因此book是一个封闭类
class Book{ 
public:
	//带参数的构造函数,其中要给成员对象初始化
	Book(int price, int year, int page):m_price(price),m_info(year,page){
	};
	void show() const;
private:
	int m_price;
	Type m_info; //Type是一个类,所以m_info是一个成员对象
};

void Type::show() const{
	cout<<"出版年份:"<<m_year<<endl;
	cout<<"该数的总页数:"<<m_page<<endl;
}


void Book::show()const{
	cout<<"价格:"<<this->m_price<<"$"<<endl;
    this->m_info.show();
}

int main()
{
	Book newbook(20,2006,344);
	newbook.show();
	return 0;
}

运行结果:
在这里插入图片描述
注意:
a. 生成封闭类对象的语句一定要让编译器能够弄明白其成员对象是如何初始化的,否则就会编译错误。

#include <iostream>
using namespace std;

class Paper{
public:
	Paper(){
		cout<<"调用顺序2"<<endl;
	}
	~Paper(){
		cout<<"调用顺序5"<<endl;
	}
};

class Book{ 
public:
	Book(){
		cout<<"调用顺序1"<<endl;
	}
	~Book(){
		cout<<"调用顺序6"<<endl;
	}
};
//Shop类内部含有2个类对象,因此Shop是一个封闭类
class Shop{ 
public:
	Shop(){
		cout<<"调用顺序3"<<endl;
	}
	~Shop(){
		cout<<"调用顺序4"<<endl;
	}
private:
	Book newbook;
	Paper newpaper;
};

int main()
{
	//创建对象,并自动调用默认的无参的构造器
	Shop newshop;
	return 0;
}

运行结果:
在这里插入图片描述

注意:
a. 封闭类对象生成时,先执行所有成员对象的构造函数,然后才执行封闭类自己的构造函数。
b. 成员对象构造函数的执行次序和成员对象在类定义中的次序一致,与它们在构造函数初始化列表中出现的次序无关。
比如:上面的例子中Shop类中先后定义了Book和Paper类的对象,由定义决定先后调用哪个类的构造函数初始化。
c. 当封闭类对象消亡时,先执行封闭类(先Shop类)的析构函数,然后再执行成员对象(paper和newbook)的析构函数。

  C++知识库 最新文章
【C++】友元、嵌套类、异常、RTTI、类型转换
通讯录的思路与实现(C语言)
C++PrimerPlus 第七章 函数-C++的编程模块(
Problem C: 算法9-9~9-12:平衡二叉树的基本
MSVC C++ UTF-8编程
C++进阶 多态原理
简单string类c++实现
我的年度总结
【C语言】以深厚地基筑伟岸高楼-基础篇(六
c语言常见错误合集
上一篇文章      下一篇文章      查看所有文章
加:2021-07-27 16:01:53  更:2021-07-27 16:02:12 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年5日历 -2024/5/2 4:48:18-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码