前言:本文主要是类和对象的介绍和使用时的一些细节和要点。
目录
初识类和对象
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.csdn.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等
不需要写的:没有资源,内置类型的成员所指向的空间没有资源需要清理
结语:希望本文能够让你有所收获。