类和对象(上)

前言:本文主要是类和对象的介绍和使用时的一些细节和要点。

目录

初识类和对象

权限访问限定符

类的大小计算

隐藏的this指针

6个默认成员函数

构造函数

编译器自动生成的构造函数

析构函数


初识类和对象

C++是一门面向对象的语言:解决对象与对象之间的关系

C语言是面向过程的语言:注重于解决问题的过程

类的三大特性:封装,继承和多态

类和C语言中的struct定义的结构体的关系:

struct Data
{
	int _year;
	int _month;
	int _day;
};
Data d1;//用struct的名称就可以表示该自定义类型


class Data
{
	int GetMonth()
	{
		return _month;
	}
    //声明
	int _year;
	int _month;
	int _day;
};
Data d1;//对象的实例化
Data d2; //1类 -> 多个对象

类兼容struct并且类是在C语言中结构体的升级版:

1.在类中不仅可以定义内置类型(比如 int,char……)的成员变量,同时也可以定义成员函数。

2.类中的成员函数可以直接调用类中的成员变量

3.类中还有访问权限:pubilc,protect,private

4.struct的名称就可以代表类型

5.类与对象的关系是一对多

6.定义的类会形成一个类域保护内部的成员。

7.类中的成员变量和函数都是声明,只有当对象实例化的时候才会为其分配空间,也就完成了定义

权限访问限定符

访问限定符 能否在类内访问 能否在类外访问
public
protect 不能
private 不能

struct定义的结构体默认的访问权限是public

struct Data
{
	int _year;
	int _month;
	int _day;
};
int main()
{
	Data d1;
	d1._year = 2024;//在类外可以访问结构体中的成员变量
	return 0;
}

类的默认访问权限是private 

class Data
{
	int GetMonth()
	{
		return _month;
	}
	int _year;
	int _month;
	int _day;
};

int main()
{
	Data d1;
	d1._year = 2024;
	return 0;
}

类的大小计算

跟计算struct定义的结构体的方法一样:需要考虑内存对其问题。

计算struct定义的结构体的大小

1、结构体变量的首地址,必须是结构体变量中的“最大基本数据类型成员所占字节数”的整数倍。(对齐)

2、第一个内置类型的变量与结构体变量的首地址对齐。
3、结构体变量中的每个成员相对于结构体首地址的偏移量,都是该成员基本数据类型所占字节的整数倍。(对齐)
4、结构体变量的总大小,为结构体变量中“最大基本数据类型成员所占字节数”(最大默认对齐数)的整数倍(补齐)

5、如果定义的结构体中有其他结构体的嵌套,用上述的方法计算嵌套的结构体的大小,最大默认对齐数,为嵌套和最外层的结构体中最大的那一个。
————————————————

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
                        
原文链接:https://blog.****.net/qq_44443986/article/details/110082316

除了以上规则,在计算类的大小时,不需要计算类中的成员函数。

例子:计算该类的大小

class Data
{
	int GetMonth()
	{
		return _month;
	}
	int _year;
	int _month;
	int _day;
};

 

如何修改默认对齐数? 

#pragma pack(1)//可以将默认对齐数改为1

 为什么要有内存对齐?

提高从内存中读取数据的效率。

隐藏的this指针

this 是一个隐藏的指针,可以在类的成员函数中使用,它可以用来指向调用对象。 当一个对象的成员函数被调用时,编译器会隐式地传递该对象的地址作为 this 指针。

#include <iostream>
using namespace std;
class Date
{
public:
	//Date(Date const* this,int year, int month, int day)隐藏的this指针
	Date(int year, int month, int day)
	{
		//this->_year = year;
		_year = year;
		_month = month;
		_day = day;
	}
private:
	int _year;
	int _month;
	int _day;
};

int main()
{
	Date d1(2024,3,2);
	return 0;
}

this指针指向的是调用该函数的对象。

隐含的this指针:

1.在实参和形参的位置不能显示写this指针(编译器会自己加上)

2.this指针可以在类中用

6个默认成员函数

什么是默认函数:

不带参的函数,全缺省的参数,编译器自动生成的函数

总结就是:不用参数就能调用的函数。

这些函数自己不写编译器都会自动生成。

构造函数

大家在用C语言写数据结构时经常忘记调用Inite函数,导致程序有错误。

构造函数:构造函数是一种特殊的函数,不开空间创建对象,用来在对象实例化的时候初始化对象的成员变量

具有以下特点:

1.函数名与类名相同

2.没有返回值

3.对象实例化时,编译器会自动调用

class Date
{
public:
    //构造函数
	Date()
	{
        _year = 0;
		_month = 0;
		_day = 0;
		cout << "Date()" << endl;
	}
private:
	int _year;
	int _month;
	int _day;
};

int main()
{
	Date d1;//对象实例化
	return 0;
}

 

4.支持重载

	Date()
	{
		_year = 0;
		_month = 0;
		_day = 0;
		cout << "Date()" << endl;
	}
	Date(int year, int month, int day)
	{
		_year = year;
		_month = month;
		_day = day;
		cout << "Date()" << endl;
	}

为什么用默认构造函数实例化对象时不写成以下形式

Date d1();
//以上的形式与无参的函数的声明区分不开

	Date()
	{
		_year = 0;
		_month = 0;
		_day = 0;
		cout << "Date()" << endl;
	}
	Date(int year = 0, int month = 0, int day = 0)
	{
		_year = year;
		_month = month;
		_day = day;
		cout << "Date()" << endl;
	}

    Date d1;

以上是两个默认构造函数,但不能再类中同时定义,原因对象实例化时,可能会导致调用歧义

 就是写了全缺省的构造函数就不要再定义不带参的构造函数。

这里建议将默认构造函数写成全缺省,因为比较好用。

编译器自动生成的构造函数

编译器自动生成的构造函数没有规定是否对内置类型处理(也就是说有的编译器会处理内置类型,有的编译器不会处理内置类型);如果是自定义类型,则调用该自定义类型的默认构造函数

默认构造函数包括:全缺省,无参和编译器自动生成的构造函数(理论上默认构造函数在类中只能有一个,否则就会调用歧义

总结:默认构造函数就是不传参数就能调用的函数

默认构造函数的调用情况:

#include <iostream>
using namespace std;
class Stack
{
public:
	Stack()
	{
		cout << "Stack()" << endl;
	}
};

class MyQueue
{
public:
	MyQueue()
	{
		_size = 0;
		cout << "MyQueue()" << endl;
	}
private:
	Stack st1;
	Stack st2;
	int _size;
};

int main()
{
	MyQueue q;
	return 0;
}

这就是实例化对象是默认构造函数的调用情况。

若自定义类型中没有默认构造函数,就会报错。

class Stack
{
public:
	Stack(int a)
	{
		cout << "Stack()" << endl;
	}
};

总结:一般情况下,都需要写默认构造函数。

少数情况下,不需要写,比如类中成员全是自定义类型。

class B
{
	
};
class C
{
};
class A
{
	B _b;
	C _c;
};

类A的成员全是自定义类型,不需要写默认构造函数,编译器自动就可以生成。


析构函数

析构函数于构造函数相对应,构造函数是对象创建的时候自动调用的,而析构函数就是对象在销毁的时候自动调用的,实现对象中资源的清理。

析构函数的特征:

1.类名前加~

2.无参,无返回值

3.可以显示调用,

4.可以自动调用

5.可以自动生成

自动生成的析构函数:对内置类型不做处理,对自定义类型调用其析构函数

class Stack
{
public:
    //析构函数
	~Stack()
	{
		free(arr);
		arr = nullptr;
	}

private:
	int* arr;
	int _capacity;
	int _top;
};

上面的类在销毁时,不会对在堆区开辟的空间进行释放。

所以要自己显示实现析构函数。 

总结:需要显示写析构函数的,如有malloc等开辟的空间,fopen等

不需要写的:没有资源,内置类型的成员所指向的空间没有资源需要清理

结语:希望本文能够让你有所收获。

上一篇:华为telnet的两种认证方式


下一篇:React Native 之 AppState(应用状态)(二十二)