当前位置:AIGC资讯 > AIGC > 正文

类和对象(上)

一、类的定义

        类有点类似c语言的结构体是一种自定义类型,但类里面除了定义一些成员变量外还有方法(成员函数),在访问的时候要指定类域。

        在类定义时首先用一个class关键字,在后面接着类的名字,然后使用{ }在花括号里面定义成员变量和成员函数,最后需要在花括号外加分号,如下:

class Stack
{
    void Init(int n = 4)
    {
        arr = (int*)malloc(sizeof(int) * n);
        if (nullptr == arr)
        {
            perror("malloc申请空间失败");
            return;
        } 
        capacity = n;
        size = 0;
    }   
    //......
    int* arr;
    size_t size;
    size_t capacity;
};

这里calss也可以替换成struct,在类里面的函数默认都为内联函数,当然它不一定都展开具体还取决于编译器。

二、访问限定符

        在定义类的时候通常会用一些关键字来限定类成员的访问,访问限定符有public,private,protected。

public修饰的成员在类外可以直接被访问;protected和private修饰的成员在类外不能直接被访问,protected和private的具体区别这里先不讲解。 访问权限作⽤域从该访问限定符出现的位置开始直到下⼀个访问限定符出现时为⽌,如果后⾯没有访问限定符,作⽤域就到}即类结束。 class定义成员没有被访问限定符修饰时默认为private,struct默认为public。 ⼀般成员变量都会被限制为private/protected,需要给别⼈使⽤的成员函数会放为public。
class Stack
{
public:
    void Init(int n = 4)
    {
        arr = (int*)malloc(sizeof(int) * n);
        if (nullptr == arr)
        {
            perror("malloc申请空间失败");
            return;
        } 
        capacity = n;
        size = 0;
    }   
    //......
private:
    int* arr;
    size_t size;
    size_t capacity;
};

三、类域

        类成员受到类域限制,在访问的时候需要指明类域,像命名空间一样使用::指明类域,如果一个函数声明在类里,定义在类外,那么在定义函数的时候就得使用::指明类域,如下:

class Stack
{
public:
    void Init(int n = 4); 
    //......
private:
    int* arr;
    size_t size;
    size_t capacity;
};
void Stack::Init(int n = 4)
{
    arr = (int*)malloc(sizeof(int) * n);
    if (nullptr == arr)
    {
        perror("malloc申请空间失败");
        return;
    } 
    capacity = n;
    size = 0; 
}  

当然访问类域内的函数通常都使用类对象加点( . ) 操作符去访问,如下:

四、实例化

        类就像是一栋房子的图纸,而用类去定义对象就类似使用图纸建造房子,这个过程就叫做实例化。

        类是不占用内存的,只有实例化后才会占内存,就像只有把图纸建造出房子后才占用地盘一样。而那么计算一个对象的内存呢?

五、对象的大小

        对象与对象之间主要区别在于成员变量的值,而同一个类的所有对象的成员函数都是一样的,所以成员函数并不储存在对象里面,只用考虑成员变量所占的内存,而成员变量占用的内存和结构体的内存计算方法一样,因为它们都存在内存对齐。需要注意的是静态成员并不是储存在对象里面(和成员函数同理),而是储存在静态区,不能算入。在类里面的静态成员与在全局申请的静态成员区别在于类成员受到类域的限制。

        如果一个类里面一个成员变量都没有那么按上面逻辑来说它实例化出来的对象占的空间应该是0,而对于这种情况编译器做了特殊处理,它所占的空间为1字节。

六、this指针

        类中有Init等成员函数,函数体中没有关于不同对象的区分,那当对象d1调⽤Init和其它函数时,该函数是如何知道应该访问的是d1对象还是d2对象呢?在这里C++给了⼀个隐含的this指针解决这⾥的问题。
        编译器编译后,类的成员函数默认都会在形参第⼀个位置,增加⼀个当前类类型的指针,叫做this指针。⽐如Stack类的Init的真实原型为, void Init(Stack* const this, int n=4)。                              C++规定不能在实参和形参的位置显⽰的写this指针(编译时编译器会处理),但是可以在函数体内显示使⽤this指针。
        类的成员函数中访问成员变量,本质都是通过this指针访问的,如Init函数中给size赋值, 可以看做this->size = 0;

总结

### 文章总结:C++类的定义与基础概念
#### 一、类的定义
- 类是一种自定义类型,类似于C语言的结构体但功能更强大。
- 类中除了可以定义成员变量外,还可以定义方法(成员函数),并在访问时指定类域。
- 类定义以`class`关键字开头,后跟类名,并在花括号`{ }`中定义成员变量和成员函数,最后以分号`;`结束。
- C++中,类内的函数默认为内联函数,但具体是否展开取决于编译器。

#### 二、访问限定符
- 类成员可通过访问限定符(public、private、protected)控制访问权限。
- public成员可从类外部直接访问;protected和private成员则不能。
- 默认情况下,类成员为private,struct的成员默认为public。
- 访问权限作用域从该访问限定符出现直至下一个访问限定符或类结束。
#### 三、类域
- 类成员受类域的限制,访问需明确指出类域。
- 使用`::`操作符访问类成员,或通过类对象及`.`操作符访问。
- 类成员函数在外定义时需指明类域,如使用`TypeName::function`格式。
#### 四、实例化
- 类不占用物理内存,直到它被用于定义对象(实例化)时才会占用内存。
- 对象的创建过程称为实例化,对象之间的主要区别在于成员变量的值。
#### 五、对象的大小
- 对象的内存大小取决于其成员变量所占用的内存,成员函数和静态成员不占用对象内存。
- 结构体与类的内存计算方式相似,均考虑内存对齐。
- 无成员变量的类实例化后的对象占用至少1字节(由编译器特殊处理)。
#### 六、this指针
- this指针是一个隐含的指针,指向当前对象的实例。
- 类成员函数的实际参数列表包含额外的this指针,用于区分不同对象调用时应访问哪个对象的成员。
- 成员函数内部访问成员变量时实际是通过this指针进行访问的。
- this指针不能在函数调用时显式传递,但可在成员函数体内部显式使用。
这些内容共同构成了C++中类的基本定义与操作方式,为后续面向对象编程提供了基础。

更新时间 2024-08-16