C++类与对象(上)

                                                     时光不语,我们都在努力 

这里是来自M--Y的专栏:C++启航

以下内容均为个人见解,如有不足还请指出

期待大家的点赞、收藏、评论(互三必回)

 

1.类引入

C语言结构体只能定义变量,在C++中,结构体不仅可以定义变量,也可以定义函数。只不过C++中结构体的定义更喜欢用class来替代。

2.类的定义

//struct className

class className

{

    //函数

     ……

    //变量

      ……

};

在C++中class为定义类的关键字 ,className为类的名字,{}中为类的主体。

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

类的两种定义方式:

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

        2.类的声明放在.h的文件中,成员函数放在.cpp文件中实现。

 //.h文件

class Data

{

public:

        void Init();

        ……

private:

        int _year;

        int _month;

        int _day;

}

 //.cpp文件

#include "xxx.h"

void Data::Init()//成员函数名前要加上类名.

{

        ……;

}

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

3.1访问限定符

 访问限定符的说明:

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

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

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

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

5.class的默认访问权限是private,struct为public(因为struct 要兼容C)

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

4.类的作用域

类定义了一个新的作用域 ,类的所有成员都在类的作用域中 在类体外定义成员时,需要使用 ::
作用域操作符指明成员属于哪个类域(如上文在.cpp文件实现成员函数) 

5.类的实例化

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

int main()

{

        Date._year=2024;//编译错误,类没有空间不能使用“.”

        return 0;

}

2.只有类实例化出的对象才具有实际的物理空间,存储成员变量

//正确代码

int main()

{

        Date d;

        d._year=2024;

}

 6.类对象模型

6.1.类对象的存储方式

类中有成员变量和成员函数,这就导致了每个由类实例化出的对象虽然变量是不同的,但是都使用一份函数,如果使用这种方式存储,所以当一个类创建多个对象时,每个对象都会多保存一份(函数),相同的代码保存多次,就会浪费空间。

解决方案:首先成员对象肯定是需要一片空间进行存储的。而成员函数就只需要在公共代码区保存一份函数的地址就好,这样需要用的时候直接去调用就行了。这就好比打篮球的时候,只需要建立几个篮球场,然后大家一起公用就行,而不需要人手一个。

6.2类的大小计算

// 类中既有成员变量,又有成员函数
class A1 {
public :
    void f1 (){}
private :
    int _a ;
};
// 类中仅有成员函数
class A2 {
public :
  void f2 () {}
};
// 类中什么都没有 --- 空类
class A3
{};
class A1 {
public :
    void f1 (){}
private :
    int _a ;
};
计算: sizeof(A1) : ____ __ sizeof(A2) : ____ __ sizeof(A3) : ____ __
结论:一个类的大小,实际就是该类中 成员变量 之和,当然要注意 内存对齐
注意空类的大小, 空类比较特殊 ,编译器给了空类 一个字节 来唯一标识这个类的对象。

7.this指针

7.1this指针的引出

 接下来我们先定义一个日期类

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 , d2 ;
        d1 . Init ( 2022 , 1 , 11 );
        d2 . Init ( 2022 , 1 , 12 );
        d1 . Print ();
        d2 . Print ();
        return 0 ;
}
对于上述类,有这样的一个问题:
Date 类中有 Init Print 两个成员函数,函数体中没有关于不同对象的区分,那当 d1 调用 Init
数时,该函数是如何知道应该设置 d1 对象,而不是设置 d2 对象呢?
C++ 中通过引入 this 指针解决该问题,即: C++ 编译器给每个 非静态的成员函数 增加了一个隐藏
的指针参数,让该指针指向当前对象 ( 函数运行时调用该函数的对象 ) ,在函数体中所有 成员变量
的操作,都是通过该指针去访问。只不过所有的操作对用户是透明的,即用户不需要来传递,编
译器自动完成

 7.2this指针的特性

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

 大家可以按照上述所说方法尝试用类定义一个栈,看看与C语言的实现有何区别。

你会发现,在C++种的栈的函数已经不需要传递Stack*的参数了,编译器编译之后该参数会自动还原,即C++中的Stack*参数是编译器维护的,C语言中是需要用户自己维护的。

  • 23
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 5
    评论
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值