目录
类的定义
类的大小
访问限定符
实例化
this指针
类的定义
class就是类,class是C++中的一个关键字
当然类也可以是C语言中的struct,C++兼容struct,甚至还有一些升级
定义类的方式
class Date
{
};
和C语言的struct一样,class是C++中定义类的一个关键字,Date是这个类的名字,我们需要在后面跟上一个 {}和;,{}里面可以放变量,函数等
定义在类里面的成员函数默认为inline
类的大小
class和struct的大小计算方式一致,和在C语言时的计算方法一致,以下博客有结构体的大小计算讲解
C语言:自定义类型:结构体-CSDN博客
明明C++的类和C语言不同,C语言只能放变量,C++不仅能放变量还能放函数,为什么还是按照C语言的方式只计算成员变量的方法来计算结构体的大小呢?
这是因为成员函数实际上并不存储在类的实例的内存空间中,它们存储在代码段内,而类的实例只存储成员变量
为什么存储在代码段?
因为在类外我们是需要定义多个该类的变量的,例如日期类:
#include<iostream>
using namespace std;
class Date
{
public:
// ...
private:
int _year;
int _month;
int _day;
};
int main()
{
Date d1;
Date d2;
Date d3;
// ...
return 0;
}
每个日期类对象d1、d2、d3毋庸置疑一定要有它们专属的变量(_year、_month、_day),这才能让它们三个都有各自的日期
那为什么不要每一个日期类对象都有一个成员函数?因为浪费
我们只需要一个函数足以,这个函数就存储在代码段中,当它们需要这个函数时就去代码段中调用这个函数,将它们专有的成员变量传过去即可,那么怎么传呢?具体看下面this指针的讲解
访问限定符
这是跟C语言不同的地方,C语言没有访问限定符的概念,比较自由
是C++一种实现封装的方式,通过访问限定符选择性的将接口给外部的用户使用
有三种访问限定符:public、private、protected
具体使用方法如下:
class Date
{
public:
void Print()
{
cout << _year << "/" << _month << "/" << _day << endl;
}
private:
int _year;
int _month;
int _day;
};
public的意思是公有的,公有的就代表可以被外部所访问,例如在main函数中可以使用
private的意思是私有的,私有的就代表不可以被外部所访问,一般都设置成员变量为私有的
protected是受保护的,它发挥作用的地方在继承的那部分,其他和private一致,不能被外部所访问
在继承中,protected外部不能访问,但是它的派生类(子类)可以访问到protected的内容,而private依旧不能访问
class定义成员没有被访问限定符修饰时默认为private,struct则默认为public,这也是他们在C++中的区别
我们要怎么访问类里面呢?
class Date
{
public:
void Print();
private:
int _year;
int _month;
int _day;
};
void Date::Print()
{
cout << _year << "/" << _month << "/" << _day << endl;
}
int main()
{
Date d1;
d1.Print();
return 0;
}
这是在类里面声明了Print()函数,在类外面定义了Print()函数
要注意的就是我们需要用::访问限定符访问Date里面,这样才能知道函数内部的_year、_month、_day是谁
访问函数只需要用 . 即可
实例化
class Date
{
public:
void Print();
// ...
private:
int _year;
int _month;
int _day;
};
int main()
{
Date d1;
d1.Print();
return 0;
}
在这个日期类中,private里的成员函数都只是声明,并不是定义,并没有开空间,所以他们不是实例化,他们就像一张图纸,只可以看不可以做
而下面的d1就是实例化出了一个日期类对象,可以使用它里面的成员函数
this指针
#include<iostream>
using namespace std;
class Date
{
public:
void Init(int year, int month, int day)
{
_year = year;
_month = month;
_day = day;
}
void Print()
{
cout << _year << "/" << _month << "/" << _day << endl;
}
private:
int _year;
int _month;
int _day;
};
int main()
{
Date d1;
Date d2;
d1.Init(2024, 7, 12);
d1.Print();
return 0;
}
在上面的代码中,有了Date类的初始化函数Init,和打印函数Print,这样我们就可以给一个Date对象初始化和打印了
运行结果:
前面有说既然类里面的函数只存在代码区只需要一份共同调用即可,那我们使用d1对象调用的时候函数里面怎么拿到d1的成员变量?为什么不是d2?
这里其实C++隐含了一个this指针,是利用了this指针解决了这个问题
我们的函数其实可以写成这样
class Date
{
public:
void Init(int year, int month, int day)
{
this->_year = year;
this->_month = month;
this->_day = day;
}
void Print()
{
cout << this->_year << "/" << this->_month << "/" << this->_day << endl;
}
private:
int _year;
int _month;
int _day;
};
照样可以运行成功,结果一样
其实函数主题和调用相当于这样
void Init(Date* const this, int year, int month, int day)
{
this->_year = year;
this->_month = month;
this->_day = day;
}
void Print(Date* const this)
{
cout << this->_year << "/" << this->_month << "/" << this->_day << endl;
}
int main()
{
Date d1;
d1.Init(&d1, 2024, 7, 12);
d1.Print(&d1);
return 0;
}
但实际上我们是不能这样自己显式的把this写在函数参数上的,编译器会报错
这些都是编译器帮我们做的是,编译器自动的把d1的地址传过去,自动用this指针访问了,所以我们不需要写
但是函数内部我们是可以使用这个this指针的,因为后续我们需要这个this指针,并不只是上面单纯的初始化、打印之类的
完