c++类class之一

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档


一、类class

1. 一些定义

类是一系列具有共同属性和行为的事物抽象。对象是类的具体化(实例化)。
属性:数据成员(int,char。。。),一系列事物公有特征
行为:成员函数的描述,一系列公有事物共同操作
类的特点:封装性,继承性,多态性,抽象性,隐藏性
封装性:顾名思义,将属性,行为封装在一个抽象类里,便于管理操作。
继承性:类的继承特性,下面会详说。
多态性:同一种行为的不同结果,下面也会详说。
抽象性:c++通过纯虚函数实现抽象类,将事物的每一部分抽象出来,在需要用到时才实例化(纯虚函数需要先继承下来才能实例化)。
隐藏性:使用者不会知道内部的实现代码,只提供功能接口。用private限制外部用户访问内部数据。

2.构造函数

构造函数的一些定义

  • 类的构造函数是类的一种特殊的成员函数,它会在每次创建类的新对象时 执行。
  • 构造函数的名称和类的名称是完全相同的,并且不会返回任何类型,也不会返回void。构造函数可以带参数,用于为某些成员变量设置初始值
class MyClass
{
public:
	MyClass(char name[], int age);	//构造函数定义

	int m_age;
	char m_name[20];
};
MyClass::MyClass(char name[], int age)
{
	strcpy(m_name, name);
	m_age = age;
}

如何使用构造函数?

int main()
{
	char name[] = "Jack";
	char name2[] = "Lily";
	MyClass temp = {name, 18};				//创建变量并初始化
	MyClass tempArr[2] = {{name, 18}, {name2, 19}}; //数组对象
	return 0;
}

考虑到并不是每次都需要使用到里面的属性,会增加一个无参构造方便使用(函数重载)。

MyClass::MyClass()										//无参构造
{
	memset(m_name, 0, sizeof(m_name));
	m_age = -1;											//初始化一些无用值
}
//创建对象时就不用传参数了
//c++提供了这么一种定义的方式,不用再写声明	MyClass() = defalut;

当然,你也可以使用默认参数来代替这种方式。

MyClass::MyClass(char name[], int age = 18){}

委托构造

实际上这种方式并不常用,它的作用也同样是方便不传参数使用对象。甚至会有点麻烦。

Tips: 为了方便展示委托构造,我需要修改一下上面的例子。(将数组name的类型换成const char*)

class MyClass
{
public:
	MyClass(const char* name, int age);		//构造函数定义
	MyClass():MyClass("委托", 18){}			//委托构造
	int m_age;
	const char* m_name;
};
MyClass::MyClass(const char* name, int age)
{
	m_name = name;
	m_age = age;
}

注意到,委托的参数(“委托”, 18)是和我们定义的有参构造相同的,顺序也是一样,那它们就一定有联系。
实际上,在我们创建一个无参的对象时,它会调用两次构造函数,首先是有参构造,把委托的2个参数传给成员变量,然后再调用无参构造

拷贝构造函数

拷贝构造主要是为了实现通过一个对象创建一个新的对象

增加一个构造函数

MyClass(const MyClass& object)	//该构造函数成为拷贝构造
{
	m_age = object.m_age;
	m_name = object.m_name;
}

匿名对象:没有具体的对象,常常用来作为函数返回值,如果调用了函数不接受返回的匿名对象,那么它就会被释放掉。

拷贝构造普通构造(上述除了拷贝外的构造)的区分
MyClass(“匿名对象”, 20);-----------------------------------------------调用普通构造
MyClass newClass = MyClass(“匿名对象”, 20);----------------匿名对象转正,不调用任何构造
MyClass newClass((对象)oldClass);-----------------------------调用拷贝构造
MyClass newClass = oldClass;---------------------------------------调用拷贝构造
void function(MyClass object){} -----函数传参---------------------调用拷贝构造
引用传参(由于没有产生新对象,不会调用)

区分的技巧:看是否是通过另一个class来创建新的class。

移动构造函数

增加一个构造函数

MyClass(MyClass&& object)	//该构造函数成为移动构造函数
{
	//该构造函数主要实现的是资源权限转移,将目标内存拿过来,并干掉目标
}

MyClass newClass = move(oldClass);//这行代码调用移动构造,oldClass为目标对象,newClass代oldClass

Tips: move的功能是将左值变为右值

3.析构函数

一些结论

  • 析构函数一般跟构造函数相反
  • new出来delete掉会自动调用析构函数,以某种方式释放掉也会调用。

深浅拷贝

经典的深浅拷贝问题: 当数据成员是指针,并做了内存申请。浅拷贝会把oldClass的内存地址一同复制过去,在释放内存时造成重复释放的问题。这时就需要深拷贝来解决。

浅拷贝

MyClass::MyClass()
{
	m_pInt = new int[3];					//给成员变量m_pInt,new了3个int类型
	memset(m_pInt, 0, sizeof(int) * 3);		//清空
}

MyClass::MyClass(const MyClass& object)//浅拷贝
{
	m_pInt = object.m_pInt;				//直接将地址赋给新的class
}

MyClass class1;								//class1
MyClass class2 = class1;					//用class1创建class2

此时我们看看地址两个class的指针指向的地址

cout << &class1.m_pInt[0] << endl;		//输出指向内存的首地址
cout << &class2.m_pInt[0] << endl;

发现是一样的。这就导致了一个问题,当调用析构函数(通常释放动作写在析构函数里)时,会释放掉内存,内存释放两次就会出现问题。
深拷贝
我们只需要修改一下拷贝函数

MyClass::MyClass(const MyClass& object)			//深拷贝
{
	m_pInt = new int[3];							//重新给新class申请内存
	memcpy(m_pInt, object.m_pInt, sizeof(int) * 3);	//内存拷贝
}

这时,释放时就是释放各自指向的内存了,不会产生冲突了。

二、如何访问类中数据

实际上,我们习惯性的将一些重要成员变量放到private中,但有时候又需要用到,那该如何处理?

1.利用构造函数初始化

class MyClass
{
public:
	MyClass(int age);	//构造函数定义
private:
	int m_age;
};

MyClass::MyClass(int age)	//构造函数实现
{
	m_age = age;				//将传进来的参数age赋值给成员变量m_age
}

2.提供接口(函数)

class MyClass
{
public:
	MyClass(int age);	//构造函数定义
	int returnAge()		//接口
	{
		return m_age;
	}
private:
	int m_age;
};

这个方法只是获取,并不能修改。

3.提供一个功能(函数)传参修改

class MyClass
{
public:
	MyClass(int age);	//构造函数定义
	void setAge(int age)		//返回引用
	{
		m_age = age;
	}
private:
	int m_age;
};
MyClass::MyClass(int age)
{
	m_age = age;
}

4.返回引用修改

class MyClass
{
public:
	MyClass(int age);	//构造函数定义
	int& returnAge()		//返回引用
	{
		int& age = m_age;
		return age;
	}
private:
	int m_age;
};
MyClass::MyClass(int age)
{
	m_age = age;
}

最后

如果文章有错误,或者有什么补充,欢迎各位指正讨论。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

小冯爱编程

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

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

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

打赏作者

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

抵扣说明:

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

余额充值