C++类与对象(上)

一.类与对象概述

C++是一门面向对象的语言,因此在C++中引入了类这个概念,并通过类的实例化来得到对象。

类的:类是一个用户定义的类型,用于封装数据(属性)和操作这些数据的方法(成员函数)。

举个例子,一个人有身高、体重、年龄、姓名等属性,我们可以通过一些成员函数来设置或者更改这些属性,也可以通过实例化来修改,或者使用这些成员函数来做一些其它的功能。我们可以把这个类看作一个人,它的所有属性都可以放在类里,而成员函数则可以对这些属性做一些操作。

对象:对象是类的一个具体实例。每个对象都有自己的数据成员的副本,和类定义的方法。

我们可以通过实例化一个对象后来访问类的属性和方法。

二.类

1.1类的格式

类书写的基本格式。

class 类名{};
struct 类名{}; 

class和struct都是定义类的关键字,如果你学过C语言你可能会觉得类和结构体有相似之处,不过结构体中不能声明函数,除此之外还有更多不一样的地方,下面我们来一一介绍。

1.2类的书写

下面我们来写一个人类。

class Person
{
public:
    Person(){}
    Person(int age,int high,int weight){}
    ~Person(){}
    void setage(int age);
private:
    int m_age;
    double m_high;
    double m_weight;
protected:
    string name;
};

类的内部可以声明函数,也可以实现函数,也可以在类外实现函数,不过要加上范围解析运算符::

例如:

void Person::setage(int age)
{
    m_age=age;
}

类内部的public、private、protected是访问限定符,可以决定一个成员函数或成员变量是否可以在类外被访问,public限定符可以在类外的任何地方访问,而private和protected我们暂时可以认为它们是一样的,由它们限定的成员函数或成员变量在类外不可以访问。protected需要在我们学习到继承后就可以区分它和private了。

它们的作用域是从一个访问限定符到下一个访问限定符出现,或者到类结束。一个类中可以出现多个相同的访问限定符。

那么如果什么访问限定符都不加,class的默认访问权限是private,struct的默认访问权限是public。

如果你想要在类内声明函数,而在类外实现函数的话,就要在函数名的前面加上::来限定函数所属的类,有了类名限定后,在一个程序里需要使用到多种数据结构时,我们就可以将尾插、尾删等操作直接定义为push、pop而不用烦恼怎么取名字了。

而类内部的与类名相同的一些函数有什么作用呢?本篇文章我们暂不介绍,下一篇文章会专门介绍。

三.实例化

1.概念

概念:⽤类类型在物理内存中创建对象的过程,称为类实例化出对象。

如果不实例化对象,我们在类外是无法访问成员变量和成员方法的。下面我们通过代码来看看。

通过图片我们可以看到如果不实例化出一个对象的话,按平时我们调用函数的方法,我们是无法访问类内函数或变量的。而在实例化出一个对象后,我们就可以正常访问类内的公有内容了。

类就像是一张图纸,我们盖房子时需要参照它来建造房子,图纸只能存储数据,不可以住人,实例化则是把房子建造了出来可以让人住进去,在建造的过程中还可以根据实际对图纸的一些数据实时更改。

2.对象大小

int、double等都是C/C++的内置类型,它们都有大小,而类作为一种自定义类型,也应该有大小,下面我们来看一下一个类是如何计算大小的。

类是以内存对齐作为计算规则的,我使用的编译器是VS2022,默认对其数是8。

计算机的内存在逻辑上被视为一个连续的地址空间,这段空间是被分成若干个字节的。

下面我们来了解一下内存对齐规则

让我们先来了解一下结构体偏移量:结构体偏移量是指在内存中,结构体成员相对于结构体起始地址的字节偏移量。每个成员在结构体中的位置决定了它的偏移量。偏移量通常是从结构体的起始位置开始计算的,以字节为单位。通常偏移量以0为开始。它表示从结构体开始到该成员的字节距离。

规则1:第⼀个成员在与结构体偏移量为0的地址处。

规则2:其他成员变量要对⻬到某个数字(对⻬数)的整数倍的地址处。

规则3:对⻬数 = 编译器默认的⼀个对⻬数 与 该成员⼤⼩的较⼩值。

规则4:结构体总⼤⼩为:最⼤对⻬数(所有变量类型最⼤者与默认对⻬参数取最⼩)的整数倍。

下面我们通过图片来具体学习怎么使用对齐规则和计算类的大小。

class Person
{
public:
    double s;
    int age;
};
int main()
{   
    Person a;
    cout << sizeof(a);
    cout << sizeof(Person);
}

在VS2022上,此程序的运行结果是两个16。下面我通过画图来带你了解一下为什么是16。

当然内存肯定不是这样分布的,图中只是为了方便。

Person类的第一个成员变量为double,占8个字节,而VS默认对齐数为8,根据规则3得到对齐数为8,我们在内存中从0开始向后数8个格子,就得到了下一个变量的偏移量。根据规则3我们可以得到对齐数为4,在向后数4个格子,最后得到的实际字节数为12,但是根据规则4结构体的大小必须为最大对齐数的整数倍,程序中double为8个字节,所以内存需要向它的整数倍对齐,所以应该为16。

这是你可能会觉得空间被浪费了,其实这样设计也是有原因的,cpu访问读取只能从内存的整数倍开始,像下面这个类,如果没有内存对齐,它就需要多次读取数据后在进行拼接,降低了效率,也可以说这样的设计是为了方便读取数据。

class Person
{
public:
    char c;
    int x;
};

同时需要注意一个空的类的大小并不是0,而是1,这是为了占位标识对象存在,如果空类的大小为0,怎么能证明它存在呢。

如果类内没有成员变量只有函数的话,其大小也为1。

class student{};
class Person
{
public:
    void getage(){}
};

四.this指针

定义:this指针是一个隐式参数,指向调用成员函数的对象。

类的成员函数中访问成员变量,本质都是通过this指针访问的。
class Person
{
public:
    void PersonInit(string name, int age)
    {
        //this=nullptr;这是错误的,this只有读的权限,这样会放大权限
        this->m_age = age;
        this->m_name = name;
    }
    Person& getage() { return *this; }
    string m_name;
    int m_age;
};

在需要返回对象自身的引用时,也可以使用thi指针。

  • 34
    点赞
  • 20
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值