C++中类的理解

类的引入

在C语言中,结构体的作用是把一些具有不同类型的变量组合在一起。

struct Student
{
    char _name[20];
    char _gender[3];
    int _age;
}

而在C++中,结构体内不止可以定义变量,还可以定义函数。

struct Student
{
    char _name[20];
    char _gender[3];
    int _age;
    
    void SetStudentInfo(const char* name, const char* gender, int age){
        strcpy(_name, name);
        strcpy(_gerder, gender);
        _age=age;
    }
};
​
int main(){
    Student s;
    s.SetStudentInfo('Bob', 'male', 18);
    return 0;
}

此时的结果提就可以被称为类,但在C++中,更喜欢使用class代替struct。

C++类的定义

class className
{
    //成员函数
    //成员变量
    
};//注意分号

类是属性和方法的合集,属性即使类中的数据,方法就是调用这些数据进行操作的函数。

1. 声明和定义全部放在类体中。此时,成员函数在类中定义,编译器会将其当作内联函数处理。

内联函数:inline,当编译器发现某段代码在调用一个内联函数时,它不是去调用该函数,而是将该函数的代码,整段插入到当前位置。这样做的好处是省去了调用的过程,加快程序运行速度。

缺点:由于每当代码调用到内联函数,就需要在调用处直接插入一段该函数的代码,所以程序的体积将增大。拿生活现象比喻,就像电视坏了,通过电话找修理工来,你会嫌慢,于是干脆在家里养了一个修理工。这样当然是快了,不过,修理工住在你家可就要占地儿了。内联函数并不是必须的,它只是为了提高速度而进行的一种修饰。

class Person//一个类
{
public://成员函数
    void showinfo()//方法:显示信息
    {
        std::cout<<_name<<std::endl;
        std::cout<<_sex<<std::endl;
        std::cout<<_age<<std::endl;
    }
public://成员变量
    char* _name;
    char* _sex;
    int _age;
};

2. 定义和声明分开放是项目中常用的。

类的访问限定符及封装

类的定义中,有publicprivateprotected来修饰成员,其中privateprotected修饰的成员不可再类的外面直接访问。

面向对象的三大特性:封装、继承、多态。

封装本质是一种管理手段,将属性(数据)和方法(接口)有机结合起来,再隐藏他们,只对外公开接口(函数)来和对象进行交互,不想给别人看的,使用protected/private进行修饰,而开放一些公有函数对成员进行合理访问。合理访问还可以理解为阅读,不合理访问可以理解为改写(不准确)。

此时可以解释为什么C语言不支持大型项目的编写,因为C语言的管理能力太弱了,不是函数就是数据,不支持面向对象。且struct默认是public的,安全性较低,模块与模块的独立性较差,因此不适合编写大型项目。

之前学C语言的时候,学过好多数据结构,比如栈,一般都是新建一个工程然后分别建立它的声明和定义等文件,此时数据和方法是分离的,是自由的。但如果再C++中,按照面向对象的考虑,一个栈就可以作为一个对象,这个对象有它的数据(动态增长的数组、长度、容量),还有方法(栈的初始化、进栈、出栈等等)。像这样的数据,应该就是私有的,因此要防止外部操作改变数据,一旦数据出错,那么方法也会受到相应的波及。这些操作要按照实际的需求让外部使用。

//stack.h
class Stack
{
public:
    void Init(int capacity=4);//缺省参数声明
private://数据私有
    int* _arr;
    int _length;
    int _capacity;
};
​
//stack.cpp
void Stack::Init(int capacity)//该方法的实现
{
    _arr=(int*)malloc(sizeof(int)*capacity);
    _length=0;
    _capacity=capacity;
}

类的实例化

类可以理解为一个房屋的图纸,这个图纸规定了一些基本的信息,因此需要根据图纸的规定修出相应的房子。

通过实例化才可以真正有一个栈,这个栈占用实际的空间。

面向对象的编程可以理解为将一个问题拆分为不同的对象,依靠参数完成对象之间的交互。

举一个洗澡的例子,如果是面向过程角度考虑,首先我进入浴室,打开水龙头,然后洗漱,然后把身体擦干,这些都是解决问题的步骤。如果是面向对象考虑,那么”万物皆对象“,首先我传递参数给门,然后我传递消息给水龙头,最后传递消息给毛巾,毛巾可以调用自己的方法擦干身体。

类对象模型

类再计算大小时不管成员函数,只管成员变量和内存对齐。

类对象的存储方法

由于一个类可以实例化很多对象,就拿栈来说,这些栈它的存储的数据可能会不一样,但是它们的方法,如进栈出栈都是一样的。所以说实例化如果再为方法开辟空间,就会造成浪费。

解决的方法是:只保存成员变量,成员函数存放在公共的代码段(常量区)。

 

  • 注意:一个类的大小,实际就是该类中的成员变量和内存对齐。但要注意空类,空类大小不是0,编译器为空类提供了一个字节表示它存在。

this指针

class Date
{
public:
    void SetDate(int year, int month, int day)
    {
        _year=year;
        _month=month;
        _day=day;
    }
private:
    int _year;
    int _month;
    int _day;
}
​
int main()
{
    Date d1;
    Date d2;
    d1.SetDate(2021,2,20);
    d2.SetDate(2022,8,19);
}

类中成员函数是公用的,此处的d1.SetDate(2021.2.20),编译器为什么知道给d1这个实例对象去设置而不给d2设置?这是因为有this的存在。

C++编译器给每个给每个非静态的成员函数增加了一个隐藏的指针参数,让该指针指向当前函数(函数运行时调用该函数的对象),在函数体中所有成员变量的操作,多是通过指针访问。

上述代码可以理解为下面的代码:

class Date
{
public:
    void SetDate(Date* this, int year, int month, int day)
    {
        //生成一个类的指针
        this -> _year=year;
        this -> _month=month;
        this -> _day=day;
    }
private:
    int _year;
    int _month;
    int _day;
}

int main()
{
    Date d1;
    Date d2;
    d1.SetDate(*d1,2021,2,20);
    d2.SetDate(*d1, 2022,8,19);
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值