类和对象 (上)

一、类的定义

class,struct 为类定义的关键字

类中的变量称为类的属性或成员变量

函数称为类的方法或成员函数

为了区分成员变量,一般习惯上成员变量会加一个特殊标识,

如前缀 _ 或 m_ ,并不是强制的,只是一些惯例,具体看公司的要求。

C++ 中 struct 也可以定义类,C++ 兼容 C 中 struct 的用法,

同时 struct 升级成了类,明显的变化是 struct 中可以定义函数。

一般情况下推荐用 class 定义类。

一个类的函数可以在类内声明、类外定义,

但前面一定要加 类名:: ,否则编译报错。

二、访问限定符

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

  • public:修饰的成员在类外可以直接被访问;

  • protected 和 private:修饰的成员在类外不能直接被访问(这两者的区别后续再讲解)。

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

如果后面没有其他访问限定符,作用域到类结束。

  • class 的成员默认是 private

  • struct 的成员默认是 public

⚠️ 注意:访问限定符后面需要加冒号。

复制代码
// 知识点:class 的成员默认是 private
class Student {
    // 【默认权限区域】
    // 这里没有写限定符,所以默认是 private。
    // 类外无法直接访问,只能在类内部的成员函数中操作。
    string name; 
    int age;     

public: 
    // 【public 权限区域】
    // 从 public: 开始,到下一个限定符(或类结束)为止,都是公开的。
    // 类外可以直接调用这些函数(这就是你提到的"接口")。
    
    // 构造函数(也是 public 的)
    Student(string n, int a) {
        // 在成员函数内部,可以随意访问 private 的 name 和 age
        name = n;
        age = a;
    }

    // 提供一个公开的接口,让外部获取名字
    void showInfo() {
        cout << "姓名:" << name << ",年龄:" << age << endl;
    }

private: 
    // 【private 权限区域】
    // 作用域从这里开始,直到类结束。
    // 这里适合放一些不想让外部知道的内部数据或辅助函数。
    int studentID; 

    void internalCheck() {
        // 这是一个内部的私有函数,外部无法调用
        cout << "正在进行内部检查..." << endl;
    }
};


// 知识点:struct 的成员默认是 public
struct DataNode {
    int val;      // 默认是 public,外部可以直接 data.val 访问
    DataNode* next; // 默认是 public
};

三、类与对象的内存特点

  • 类实例化出的每个对象,都有独立的数据空间;

  • 对象中包含成员变量,成员函数是多个对象共用的;

  • 类即使只有成员函数,也会占用至少1字节的内存(用于占位标识)。

四、this 指针 指向对象的指针

指向的是"当前正在调用这个函数的那个对象"

一个类的两个对象,使用同一个成员函数

函数如何分辨哪个对象调用的函数?

用 this 指针 悄悄把对象指针传过去

this 是一个形参,把对象地址传过去

在 形参、实参都不能显式的去写 this

函数内可以显式的加上 this,结果为类指针

实际代码中什么时候需要显式写 this

1、解决形参和成员变量"撞名"的尴尬

这是最常见的用法。为了代码可读性,我们常把构造函数的形参名设得和成员一样,这时候必须用 this 来区分:

复制代码
class Student {
public:
    int age;
    Student(int age) {
        // 这里的 age 是形参,this->age 才是成员变量
        this->age = age; 
    }
};

2、实现"链式调用"(返回当前对象本身)

如果你想让函数调用像流水线一样连起来(比如 obj.setA(1).setB(2)),就需要返回 *this

复制代码
class Calculator {
public:
    int val = 0;
    // 返回类指针(或者类引用 *this)
    Calculator* add(int x) {
        val += x;
        return this; // 把当前对象的地址抛回去,方便下一次调用
    }
};
// 使用:calc.add(5).add(10);

3、把当前对象作为参数传给别的函数

比如当前对象想把自己"介绍"给另一个对象或全局函数:

复制代码
void globalFunc(Student* s);

class Student {
public:
    void introduce() {
        globalFunc(this); // 显式把当前对象的指针传出去
    }
};

this 默认认为存在栈 vs 优化存在寄存器

相关推荐
小新1102 小时前
qt creator 将qInfo的输出日志写入日志文档,方便查看
开发语言·qt
我材不敲代码2 小时前
Python 函数核心:位置参数与关键字参数详解
java·前端·python
hssfscv2 小时前
QT的学习记录1
开发语言·qt·学习
SunnyDays10113 小时前
Python操作Excel批注:从基础添加到高级自定义的完整指南
开发语言·python·excel
Yyyyyy~3 小时前
【C++】数组篇
开发语言·c++
qq_333120973 小时前
C++高并发内存池的整体设计和实现思路_C 语言
java·c语言·c++
牛肉在哪里3 小时前
ros2 从零开始27 编写广播C++
开发语言·c++·机器人
mh_f3 小时前
33.批量通过GET链接下载图片到指定文件夹下
java
金銀銅鐵3 小时前
[Java] 如何理解 class 文件中方法的 access flags?
java·后端