C++入门,类和对象(上)

文章目录

目录

1.面向过程和面向对象初步认识

2.类的引入

3.类的定义

4.类的访问限定符及封装

     4.1 访问限定符(public,protected,private)

   4.2封装

5.类的作用域

6.类的实例化

7.类对象模型

7.1计算类对象的大小

7.2类对象的存储方式

7.3结构体内存对齐规则

1.为什么要内存对齐?

8.this指针

8.1this指针的引出

8.2 this指针的特性

9.对比一下c++和c语言实现栈的方法

9.1C语言实现栈

9.2C++实现栈

总结

 


1.面向过程和面向对象初步认识

  C语言是面向过程的,关注的是过程,分析出求解问题的步骤,通过函数调用逐步解决问题。C++是基于面向对象的,关注的是对象,将一件事情拆分成不同的对象,靠对象之间的交互完成。

  比如洗衣服,C语言关注:拿个盆-放水-放衣服-放洗衣服-手搓-换水-拧干-晾衣服,C++关注:总共有四个对象,人,衣服,洗衣粉,洗衣机,整个洗衣服的过程,人将衣服放进洗衣机,倒入洗衣粉,启动洗衣机。整个过程主要是:人,衣服,洗衣粉,洗衣机四个对象之间交互完成的。

2.类的引入

        C语言结构体中只能定义变量,在C++中,结构体不仅可以定义变量,也可以定义函数,比如:之前在数据结构中,用C语言形成的栈,结构体中只能定义变量(数组,top,和容量);现在以C++方式实现,struct中也可以定义函数

struct Stack
{
    void Init(size_t capacity)
    {
        _array=(int *)malloc(sizeof(int)*capacity);
        _capacity = capacity;
        _size = 0;
    }

    ....

    int * array;
    size_t capacity;
    _size = 0;
}


int main()
{
    Stack s;
    s.Init(10);
    ...
}

上面结构体的定义,在c++中更喜欢用class代替。

3.类的定义

class className
{
    //类体:由成员函数和成员变量组成

 }; //记得有分号

类体重内容为类的成员:类的变量称为类的属性或成员变量;类中的函数称为类的方法或者成员函数。

类的两种定义方式:

1.声明和定义全部放在类体中,需注意:成员函数如果在类中定义,编译器可能会将其当成内联函数处理。

class Person
{
    public:
        void showInfo()
        {
            ...
        }
    public:
        char* _name;
        char* sex;
        ...
}

2.类声明在.h中,成员函数放在cpp中,注意,成员函数名前需要加类名::

//person.h

class Person
{
    public:
        void showInfo();
    public:
        char * name;
        ...
}


//person.cpp

#include "person.h"

void Person::showInfo()
{
    ...
}

一般第二种更为规范

成员变量命名规则的建议:

class Date
{
    public:
        void Init(int year)
        {
    //这里无法区分是形参 还是成员变量
            year = year;
        }
    private:
        int year;
};


//所以一般建议如下:

class Date
{
    public:
        void Init(int year)
        {
            _year = year;
        }
        
    private:
        int _year;
};

4.类的访问限定符及封装

     4.1 访问限定符(public,protected,private)

        C++实现封装的方式:用类将对象的属性与方法结合在一起,让对象更加完善,通过访问权限选择性的将其接口提供给外部的用户使用。

  访问限定符说明:

   1.public修饰的成员在类外可以直接被访问

   2.protected和private修饰的成员在类外不能直接被访问

   3.访问权限作用域从该访问限定符出现的位置开始直到下一个访问限定符出现时为止

   4.如果后面没有访问限定符,作用域到}即类结束

   5.class的默认访问权限是private,struct为public

注:访问限定符只在编译时有用,当数据映射到内存后,没有任何访问限定符的区别

    question:struct和class的区别是啥?

    answer:C++需要兼容C,所以c++中struct可以当成结构体使用,另外struct也可以定义类。和class定义类相同。区别是struct默认权限是public,class默认权限是private,在继承和模板参数列表位置,struct和类也有区别,后续说明。

   4.2封装

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

        封装:将数据和操作数据的方法有机结合,隐藏对象的属性和实现细节,仅对外公开接口来和对象进行交互。

        封装本质是一种管理,让用户更方便使用类。

5.类的作用域

 类定义了一个新的作用域,类的所有成员都在类的作用域中。在类外定义成员时,需要使用::作用域操作符指明成员属于哪个类域。

6.类的实例化

 用类类型创建对象的过程,称为类的实例化

 1.类是对对象进行描述的,是一个模型一样的东西,限定了类有哪些成员,定义出一个类并没有分配实际的内存空间用来存储它

 2.一个类可以实例化出多个对象,实例化出的对象,占用实际的物理空间,存储类成员变量

 3.类实例化出的对象就像是根据建筑图纸设计出房子,类就是建筑图纸。

7.类对象模型

7.1计算类对象的大小

        类中既有成员变量,又有成员函数,那么一个类的大小是否为成员变量大小+成员函数,成员函数存储在哪里?详见下文分析。

7.2类对象的存储方式

        a.如果类中存储了成员变量和成员函数 这种存储方法的缺点是:每个成员的成员变量不同,但是调用同一份函数,如果按这种方式存储,相同代码保存多次,会很大的浪费空间。

        b.类中的成员变量存储,成员函数放在代码段

可以通过编译器来查看:

//类中有成员变量,也有成员函数
class A{
    public:
        void f();
    private:
        int _a;
};


//类中仅有成员函数
class A1{
    public :
        void f();
};

//类中什么都没有 --空类

class A3{
};

sizeof(A) == 4

sizeof(A1) ==

sizeof(A2) == 1;

结论:一个类的大小,就是该类中的成员变量大小之和,要注意内存对齐。空类的大小比较特殊,编译器给了空类一个字节来标识这个类的对象。

7.3结构体内存对齐规则

  •  第一个成员与结构体偏移量为0的地址处
  • 其他成员变量要对齐到某个数字(对齐数)的整数倍的地址处。

        对齐数 = 编译器默认对齐数与该成员大小的较小值    vs下默认对齐数是8

  •  结构体总大小为:最大对齐数(所有变量类型最大者与默认对齐参数取最小)的整数倍
  • 如果嵌套了结构体,嵌套的结构体对齐到自己的最大对齐数的整数倍处,结构体的整体大小就是所有最大对齐数(含嵌套结构体的对齐数)的整数倍。

1.为什么要内存对齐?

1.平台原因

不是所有硬件平台都可以随意访问任意地址上的数据,某些硬件平台只可以在某些地址取特定类型的数据,否则会有硬件异常

2.性能原因

数据结构尽可能在自然边界上对齐。如果访问没有对齐的内存,处理器需要两次内存访问,对齐之后只要一次访问。(空间换时间)

这里可以参考这篇文章:深度刨析为何要内存对齐_为什么要内存对齐_月半木斤的博客-CSDN博客

8.this指针

8.1this指针的引出

class Date
{
    public:
        void Init(int year, int month, int day)
        {
            _year = year;
            _month = month;
            _day = day;
        }


        void Print()
        {
            ///
        }

    private:
        int _year;
        int _month;
        int _day;
};

int main()
{
     Date d1,d2;
     d1.Init(2023,6,15);
     d2.Init(2023,6,16);
     return 0;
}

Date类中有两个成员函数,函数体中没有关于不同对象的区分,d1调用init函数,它是怎么直到去设置d1,而不是d2?

C++通过this指针来解决这种问题,即:C++编译器给每个”非静态成员函数“增加了一个隐藏的指针参数,让该指针指向当前对象(函数运行时调用该函数的对象),在函数体中所有”成员变量“的操作,都是通过该指针去访问。只不过所有的操作对用户是透明的,即用户不需要来传递,编译器自动完成。

8.2 this指针的特性

1.this指针的类型,类类型*const,即成员函数中,不能给this指针赋值
2.只能在”成员函数"的内部使用
3.this指针本质上是“成员函数”的形参,当对象调用成员函数时,将对象地址作为实参传递给this形参,所以对象中不存储this指针。this存储在栈中
4.this指针是“成员函数”第一个隐含的指针形参,一般情况由编译器通过ecx寄存器自动传递,不需要用户传递



void Disaplay()
{
    ...
}

//编译器处理成员函数隐含的this指针
void Dispaly(Date * this)
{
    cout<<this->_year<<endl;
}

1.this是一个隐含形参,存在栈里,vs里面存在ecx寄存器中存储(方便频繁调用)

2.this指针可以为空,详见如下代码:


class Date{
    ....


}


int main()
{
    Date d1;
    Date d2;

    ...

    Date * ptr = nullptr;
    // 正常运行,因为ptr虽然是一个空指针,
    //但是fun存在代码段  call ...,此处并没有解引用,没有去ptr的对象中去找
    ptr->fun();
 
    fun() 不能直接调用,因为只能在类域里找,prt->就是告诉了这个类域,ptr是一个空指针,传给this

    //这段代码会崩溃,因为Init里面需要一个实例化对象,ptr是空指针,this去解引用,空指针解引用就会崩溃
    ptr->Init(2022,2,3); 

    //也会崩溃,在对象里,空指针解引用崩溃
    ptr->year;
    
    (*ptr).fun();  //正常运行,func不存在对象中,在代码段,(*ptr)的作用就是传递给this

}

9.对比一下c++和c语言实现栈的方法

9.1C语言实现栈

可以参考之前博客,可以观察到,Stack相关操作函数:

1.每个函数的第一个参数都是stack*,

2.函数中必须要对第一个参数检测,因为参数可能是null,

3.函数中都是通过stack*参数操作栈

4.调用时必须传递stack结构变量的地址

结构体中只能定义存放数据的结构,操作数据的方法不能放在结构体中,即数据和操作数据的方式分离,实现上很复杂,容易出错。

9.2C++实现栈

typedef int DataType;
class Stack()
{
    public:
        void Init()
        {
            _array = (DataType*)malloc(sizeof(DataType)*4);
            
            _capacity = 4;
            
            _size = 0;
        }

        void  push(DataType data)
        {
            CheckCapacity();
            _array[size] = data;
            _size++;
        }

        void pop()
        {
            if((Enpty())
                return;
            _size--;
        }


        //....

        private:
            DataType * _array;
            int _capacity;
            int _size;
}

C++中通过类可以将数据和操作数据的方法结合,通过访问权限可以控制哪些方法在类外可以调用,即封装,使用时就像使用自己的成员,不需要传递stack*参数。c++中stack*参数由编译器维护,C语言中需要用户自己维护。

总结

本文主要介绍了c++中类和对象的初步认识,技术有限,如有错误请指正。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值