Lesson02---类与对象(上篇)

目录

一、面向过程与面向对象初步认识

[1.1 通俗概念](#1.1 通俗概念)

[1.2 代码对比](#1.2 代码对比)

面向过程

面向对象

注意点

[二、类的引入(C vs C++ 结构体)](#二、类的引入(C vs C++ 结构体))

[2.1 通俗概念](#2.1 通俗概念)

注意点

[三、类的定义(两种方式 + 命名规则)](#三、类的定义(两种方式 + 命名规则))

[3.1 通俗概念](#3.1 通俗概念)

[3.2 两种定义方式](#3.2 两种定义方式)

[方式 1:声明和定义都在类内(适合短小函数)](#方式 1:声明和定义都在类内(适合短小函数))

[方式 2:声明在.h 文件,定义在.cpp 文件(推荐)](#方式 2:声明在.h 文件,定义在.cpp 文件(推荐))

[3.3 命名规则(避坑重点)](#3.3 命名规则(避坑重点))

错误示例(形参和成员变量冲突)

[正确示例(加前缀 / 后缀区分)](#正确示例(加前缀 / 后缀区分))

[3.4 注意点](#3.4 注意点)

四、访问限定符及封装特性

[4.1 通俗概念](#4.1 通俗概念)

[4.2 三种访问限定符](#4.2 三种访问限定符)

[4.3 封装特性(面向对象三大特性之一)](#4.3 封装特性(面向对象三大特性之一))

通俗解释

[面试题:C++ 中 struct 和 class 的区别](#面试题:C++ 中 struct 和 class 的区别)

注意点

五、类的作用域

[5.1 通俗概念](#5.1 通俗概念)

注意点

[六、类的实例化(类 vs 对象)](#六、类的实例化(类 vs 对象))

[6.1 通俗概念](#6.1 通俗概念)

注意点

七、类对象大小的计算(内存对齐)

[7.1 通俗概念](#7.1 通俗概念)

[7.2 内存对齐规则(核心重点)](#7.2 内存对齐规则(核心重点))

[7.3 注意点](#7.3 注意点)

[八、this 指针(特性 + 面试题)](#八、this 指针(特性 + 面试题))

[8.1 通俗概念](#8.1 通俗概念)

[8.2 this 指针的五大特性](#8.2 this 指针的五大特性)

[8.3 面试题(this 指针经典题)](#8.3 面试题(this 指针经典题))

[题目 1:以下代码运行结果是?(A. 编译报错 B. 运行崩溃 C. 正常运行)](#题目 1:以下代码运行结果是?(A. 编译报错 B. 运行崩溃 C. 正常运行))

[题目 2:以下代码运行结果是?(A. 编译报错 B. 运行崩溃 C. 正常运行)](#题目 2:以下代码运行结果是?(A. 编译报错 B. 运行崩溃 C. 正常运行))

[8.4 注意点](#8.4 注意点)

[九、C 与 C++ 实现 Stack 的对比](#九、C 与 C++ 实现 Stack 的对比)

[9.1 代码对比(核心差异)](#9.1 代码对比(核心差异))

[(1)C 语言实现(数据与方法分离)](#(1)C 语言实现(数据与方法分离))

[(2)C++ 实现(数据与方法封装)](#(2)C++ 实现(数据与方法封装))

[9.2 核心差异对比](#9.2 核心差异对比)

[9.3 注意点](#9.3 注意点)

十、学习总结与建议


一、面向过程与面向对象初步认识

1.1 通俗概念

  • 面向过程(C 语言):关注「步骤」,比如洗衣服要 "放水→放衣服→搓洗→换水→拧干→晾晒",一步步按流程来,全程盯着操作。
  • 面向对象(C++):关注「角色」,把洗衣服拆成 "人、衣服、洗衣粉、洗衣机"4 个对象,人不用管洗衣机怎么转,只需让对象们配合完成,不用纠结内部细节。

1.2 代码对比

面向过程

cpp 复制代码
#include <stdio.h>
// 步骤函数:放水、放衣服、洗衣、甩干、晾晒
void FillWater() { printf("放水\n"); }
void PutClothes() { printf("放衣服和洗衣粉\n"); }
void Wash() { printf("洗衣机搅拌清洗\n"); }
void SpinDry() { printf("甩干\n"); }
void HangClothes() { printf("晾晒\n"); }

int main() {
    // 按步骤调用,全程关注流程
    FillWater();
    PutClothes();
    Wash();
    SpinDry();
    HangClothes();
    return 0;
}

面向对象

cpp 复制代码
#include <iostream>
using namespace std;

// 定义对象(类)
class Person {
public:
    void OperateWashingMachine() { cout << "人操作洗衣机" << endl; }
};

class WashingMachine {
public:
    void Wash() { cout << "洗衣机搅拌清洗" << endl; }
    void SpinDry() { cout << "洗衣机甩干" << endl; }
};

class Clothes {
public:
    void BeWashed() { cout << "衣服被清洗" << endl; }
};

int main() {
    // 创建对象,靠对象交互
    Person p;
    WashingMachine wm;
    Clothes c;

    p.OperateWashingMachine();
    c.BeWashed();
    wm.SpinDry();
    cout << "人晾晒衣服" << endl;
    return 0;
}
cpp 复制代码
人操作洗衣机
衣服被清洗
洗衣机甩干
人晾晒衣服

注意点

  • C++ 兼容面向过程写法,是「基于面向对象」而非纯面向对象;
  • 面向对象三大特性:封装、继承、多态(本章重点讲封装);
  • 面试小提示:常考 "面向过程与面向对象的区别",核心答 "关注重点不同(步骤 vs 对象)、数据与方法关系不同(分离 vs 封装)"。

二、类的引入(C vs C++ 结构体)

2.1 通俗概念

C 语言的结构体只能放变量,C++ 的结构体(struct)既能放变量也能放函数,相当于 "增强版结构体"。C++ 更推荐用class关键字定义类,功能和 struct 一致,仅默认访问权限不同。

cpp 复制代码
#include <iostream>
#include <cstdlib>
#include <cassert>
using namespace std;

typedef int DataType;
// C++结构体:可定义变量+函数
struct Stack {
    // 初始化栈
    void Init(size_t capacity) {
        _array = (DataType*)malloc(sizeof(DataType) * capacity);
        if (nullptr == _array) {
            perror("malloc申请空间失败");
            return;
        }
        _capacity = capacity;
        _size = 0;
    }

    // 入栈(简化版,未实现扩容)
    void Push(const DataType& data) {
        assert(_size < _capacity); // 防止越界
        _array[_size] = data;
        ++_size;
    }

    // 取栈顶元素
    DataType Top() {
        assert(_size > 0); // 栈空不可访问
        return _array[_size - 1];
    }

    // 销毁栈
    void Destroy() {
        if (_array) {
            free(_array);
            _array = nullptr;
            _capacity = 0;
            _size = 0;
        }
    }

    // 成员变量
    DataType* _array;   // 栈数组
    size_t _capacity;   // 容量
    size_t _size;       // 有效元素个数
};

int main() {
    Stack s;
    s.Init(10); // C++可直接通过对象调用函数(C语言不行)
    s.Push(1);
    s.Push(2);
    s.Push(3);
    cout << "栈顶元素:" << s.Top() << endl; // 输出3
    s.Destroy();
    return 0;
}
cpp 复制代码
栈顶元素:3

注意点

  • C 语言中不能写s.Init(10),需写StackInit(&s, 10),还要手动传递结构体指针;
  • C++ 中 struct 和 class 的核心区别:默认访问权限(struct 默认 public,class 默认 private);
  • 开发中用 class 定义类更规范,struct 主要用于兼容 C 语言代码。

三、类的定义(两种方式 + 命名规则)

3.1 通俗概念

类就是 "自定义类型的模板",里面可以放变量(属性)和函数(方法),用class关键字定义,结尾必须加;(容易忘!)

3.2 两种定义方式

方式 1:声明和定义都在类内(适合短小函数)

cpp 复制代码
#include <iostream>
using namespace std;

class Person {
public:
    // 成员函数:类内定义(编译器可能当内联函数)
    void ShowInfo() {
        cout << _name << " " << _sex << " " << _age << endl;
    }

public:
    // 成员变量:加前缀_区分形参(避坑重点)
    char* _name;  // 姓名
    char* _sex;   // 性别
    int _age;     // 年龄
};

int main() {
    Person p;
    p._name = (char*)"张三";
    p._sex = (char*)"男";
    p._age = 20;
    p.ShowInfo(); // 输出:张三 男 20
    return 0;
}

方式 2:声明在.h 文件,定义在.cpp 文件(推荐)

(1)头文件 Person.h(声明)

cpp 复制代码
#ifndef PERSON_H // 防止头文件重复包含(必加)
#define PERSON_H

#include <iostream>
using namespace std;

class Person {
public:
    // 成员函数声明
    void ShowInfo();

public:
    // 成员变量声明
    char* _name;
    char* _sex;
    int _age;
};

#endif // PERSON_H

(2)源文件 Person.cpp(定义)

cpp 复制代码
#include "Person.h"

// 成员函数定义:必须加Person::(作用域限定符)
void Person::ShowInfo() {
    cout << _name << " " << _sex << " " << _age << endl;
}

(3)主文件 main.cpp(调用)

cpp 复制代码
#include "Person.h"

int main() {
    Person p;
    p._name = (char*)"李四";
    p._sex = (char*)"女";
    p._age = 18;
    p.ShowInfo(); // 输出:李四 女 18
    return 0;
}

3.3 命名规则(避坑重点)

错误示例(形参和成员变量冲突)

cpp 复制代码
class Date {
public:
    void Init(int year) {
        year = year; // 错误:编译器分不清是形参还是成员变量
    }
private:
    int year;
};

正确示例(加前缀 / 后缀区分)

cpp 复制代码
// 方式1:加前缀_(最常用)
class Date {
public:
    void Init(int year) {
        _year = year; // 清晰区分
    }
private:
    int _year;
};

// 方式2:加后缀m(公司规范)
class Date {
public:
    void Init(int year) {
        mYear = year;
    }
private:
    int mYear;
};

3.4 注意点

  • 类结尾的;不能漏,漏了会编译报错;
  • 类内定义的长函数不推荐,编译器可能不视为内联,建议分离定义;
  • 头文件必须加 "防止重复包含" 宏(#ifndef/#define/#endif),否则多文件包含会报 "重定义" 错误。

四、访问限定符及封装特性

4.1 通俗概念

访问限定符就是给类的成员 "设权限":有的成员能外部访问(比如手机开机键),有的不能(比如手机内部主板),这就是封装的核心 ------ 隐藏细节,只暴露接口。

4.2 三种访问限定符

cpp 复制代码
#include <iostream>
using namespace std;

class Person {
public:
    // 公有成员:类外可访问(接口)
    void ShowInfo() {
        // 类内可访问所有成员(公有、保护、私有)
        cout << _name << " " << _age << endl;
    }

protected:
    // 保护成员:类外不可访问(后续继承用)
    char* _name = (char*)"王五";

private:
    // 私有成员:类外不可访问(隐藏数据)
    int _age = 25;
};

int main() {
    Person p;
    p.ShowInfo(); // 正确:public成员可访问,输出:王五 25

    // 错误示例1:访问protected成员
    // p._name = (char*)"赵六"; // 编译报错:无法访问protected成员

    // 错误示例2:访问private成员
    // p._age = 30; // 编译报错:无法访问private成员

    return 0;
}
cpp 复制代码
王五 25

4.3 封装特性(面向对象三大特性之一)

通俗解释

封装就像手机:用户只需用 "开机键、屏幕、充电口"(public 接口),不用管内部 CPU、电池怎么工作(private/protected 细节),厂商把内部零件藏起来,只暴露必要接口,既安全又方便。

面试题:C++ 中 struct 和 class 的区别

标准答案

  1. 兼容 C 语言:struct 可当结构体用,class 只能定义类;
  2. 默认访问权限:struct 默认 public,class 默认 private;
  3. 继承和模板参数:后续讲解(struct 默认 public 继承,class 默认 private 继承)。

注意点

  • 访问限定符只在「编译时」有用,编译后内存中没有权限区别;
  • 开发建议:成员变量设为 private/protected,通过 public 成员函数(比如 GetName、SetAge)访问,防止误修改;
  • 面试小提示:"什么是封装?"------ 答:将数据和操作数据的方法结合,隐藏细节,仅暴露接口供交互。

五、类的作用域

5.1 通俗概念

类就像一个 "专属文件夹",里面的成员(变量、函数)都在这个文件夹里。如果要在文件夹外面用里面的函数,得告诉编译器这个函数属于哪个文件夹(用::作用域限定符)。

cpp 复制代码
#include <iostream>
using namespace std;

class Person {
public:
    // 成员函数声明(在Person这个"文件夹"里)
    void PrintPersonInfo();

private:
    char _name[20] = "孙七";
    char _gender[3] = "男";
    int _age = 30;
};

// 类外定义成员函数:必须加Person::(指明所属"文件夹")
void Person::PrintPersonInfo() {
    cout << _name << " " << _gender << " " << _age << endl;
}

// 错误示例:不加类名::,编译器以为是全局函数
// void PrintPersonInfo() {
//     cout << _name << endl; // 编译报错:_name未声明
// }

int main() {
    Person p;
    p.PrintPersonInfo(); // 正确:输出 孙七 男 30
    return 0;
}
cpp 复制代码
孙七 男 30

注意点

  • 类内成员相互访问不用加限定符,类外必须加类名::
  • 若全局函数与类成员函数同名,用::函数名访问全局函数,用对象.函数名访问成员函数;
  • 类的作用域独立,成员变量名可与全局变量名同名(优先访问类内成员)。

六、类的实例化(类 vs 对象)

6.1 通俗概念

类是 "设计图",比如建筑设计图,只画了房子的结构,没有实际空间;对象是 "按设计图盖的房子",有实际空间,能住人。用类创建对象的过程,就是实例化。

cpp 复制代码
#include <iostream>
using namespace std;

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() {
    // 错误示例1:直接给类的成员变量赋值(类是设计图,没有空间)
    // Date::_year = 2024; // 编译报错:语法错误

    // 正确:实例化对象(按设计图盖房子)
    Date d1, d2;
    d1.Init(2024, 5, 20); // 给d1对象赋值
    d2.Init(2024, 5, 21); // 给d2对象赋值
    d1.Print(); // 输出:2024-5-20
    d2.Print(); // 输出:2024-5-21

    // 验证对象占空间(仅存储成员变量)
    cout << "Date对象大小:" << sizeof(d1) << endl; // 输出12(3个int,每个4字节)
    return 0;
}
cpp 复制代码
2024-5-20
2024-5-21
Date对象大小:12

注意点

  • 一个类可以实例化多个对象,每个对象的成员变量独立存储(值不同),成员函数共用(存在公共代码区);
  • 类本身不占内存,只有实例化后的对象才占内存,存储成员变量;
  • 面试小提示:"类和对象的关系?"------ 答:类是对象的模板,对象是类的实例,类定义属性和方法,对象存储数据并执行方法。

七、类对象大小的计算(内存对齐)

7.1 通俗概念

对象的大小只算成员变量的大小,成员函数存在公共代码区不算。但成员变量的存储要遵循 "内存对齐" 规则,就像摆箱子,大箱子旁边不能塞小碎片,要按固定大小对齐,提高访问效率。

cpp 复制代码
#include <iostream>
using namespace std;

// 类1:有成员变量和成员函数
class A1 {
public:
    void f1() {}
private:
    int _a; // 4字节
};

// 类2:仅有成员函数
class A2 {
public:
    void f2() {}
};

// 类3:空类(无成员)
class A3 {};

int main() {
    cout << "sizeof(A1) = " << sizeof(A1) << endl; // 输出4
    cout << "sizeof(A2) = " << sizeof(A2) << endl; // 输出1
    cout << "sizeof(A3) = " << sizeof(A3) << endl; // 输出1
    return 0;
}

结果分析

  • A1:只算_a的 4 字节,成员函数 f1 不算;
  • A2:无成员变量,但编译器给 1 字节(唯一标识这个类的对象,避免大小为 0);
  • A3:空类,编译器同样分配 1 字节(原因同上)。

7.2 内存对齐规则(核心重点)

  • 第一个成员放在偏移量为 0 的位置;
  • 其他成员要对齐到 "对齐数" 的整数倍(对齐数 = 编译器默认对齐数(VS 为 8)和成员大小的较小值);
  • 对象总大小是 "最大对齐数" 的整数倍;
  • 嵌套结构体:嵌套的结构体对齐到自己的最大对齐数,总大小是所有最大对齐数的整数倍。
cpp 复制代码
#include <iostream>
using namespace std;

class A {
private:
    char _c1; // 大小1,对齐数1,偏移量0
    int _i;   // 大小4,对齐数4,偏移量4(1的下一个4的倍数)
    char _c2; // 大小1,对齐数1,偏移量8(4+4=8)
};

int main() {
    cout << "sizeof(A) = " << sizeof(A) << endl; // 输出12
    return 0;
}

计算过程

  • 实际占用:1(_c1)+3(填充)+4(_i)+1(_c2)+3(填充)=12;
  • 最大对齐数是 4(_i 的对齐数),12 是 4 的整数倍,符合规则。

7.3 注意点

  • 内存对齐是 "空间换时间",牺牲部分内存提高 CPU 访问效率;
  • 空类大小为 1 字节,仅用于标识对象,不存储实际数据;
  • 面试小提示:"为什么要内存对齐?"------ 答:CPU 按固定大小读取内存,对齐后无需拆分数据,提高访问效率。

八、this 指针(特性 + 面试题)

8.1 通俗概念

每个非静态成员函数都藏着一个 "隐形指针",叫 this 指针,它自动指向调用这个函数的对象。比如 d1 调用 Init 函数时,this 就指向 d1,函数里操作的成员变量,其实都是 this 指针指向的对象的变量。

cpp 复制代码
#include <iostream>
using namespace std;

class Date {
public:
    // 编译器实际处理:void Init(Date* const this, int year, int month, int day)
    void Init(int year, int month, int day) {
        // 编译器实际处理:this->_year = year;
        _year = year;
        _month = month;
        _day = day;
    }

    // 编译器实际处理:void Print(Date* const this)
    void Print() {
        // 编译器实际处理:cout << this->_year << "-" << this->_month << "-" << this->_day << endl;
        cout << _year << "-" << _month << "-" << _day << endl;
    }

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

int main() {
    Date d1, d2;
    // 编译器实际处理:d1.Init(&d1, 2024, 5, 20);
    d1.Init(2024, 5, 20);
    // 编译器实际处理:d2.Init(&d2, 2024, 5, 21);
    d2.Init(2024, 5, 21);
    d1.Print(); // 输出:2024-5-20
    d2.Print(); // 输出:2024-5-21
    return 0;
}

8.2 this 指针的五大特性

  • 类型:类类型* const(比如Date* const),不能给 this 赋值(不能改指向);
  • 只能在非静态成员函数内部使用;
  • 是函数形参,存在栈上(VS 用 ecx 寄存器传递),对象中不存储;
  • 自动传递,用户不用手动写参数;
  • 可在函数体内显式使用(比如cout << this << endl;)。

8.3 面试题(this 指针经典题)

题目 1:以下代码运行结果是?(A. 编译报错 B. 运行崩溃 C. 正常运行)

cpp 复制代码
class A {
public:
    void Print() {
        cout << "Print()" << endl;
    }
private:
    int _a;
};

int main() {
    A* p = nullptr;
    p->Print();
    return 0;
}

答案:C. 正常运行

分析:

  • p->Print()调用的是成员函数,函数在公共代码区,不用访问 p 指向的内存;
  • 函数体内没用到成员变量(没操作this->_a),this 为空不影响,所以正常运行。

题目 2:以下代码运行结果是?(A. 编译报错 B. 运行崩溃 C. 正常运行)

cpp 复制代码
class A {
public:
    void PrintA() {
        cout << _a << endl;
    }
private:
    int _a;
};

int main() {
    A* p = nullptr;
    p->PrintA();
    return 0;
}

答案:B. 运行崩溃

分析:

  • 函数体内访问_a,本质是this->_a,而 this 指针为空(p 是 nullptr);
  • 访问空指针指向的内存,触发内存错误,运行崩溃。

8.4 注意点

  • this 指针不能为空,但若函数体内不访问成员变量,即使 this 为空也不会崩溃;
  • 静态成员函数没有 this 指针(后续讲解),不能访问非静态成员变量;
  • 面试小提示:"this 指针存在哪里?"------ 答:作为函数形参,存在栈上(VS 中通过 ecx 寄存器传递)。

九、C 与 C++ 实现 Stack 的对比

9.1 代码对比(核心差异)

(1)C 语言实现(数据与方法分离)

cpp 复制代码
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>

typedef int DataType;
typedef struct Stack {
    DataType* array;
    int capacity;
    int size;
} Stack;

// 初始化:需手动传递Stack*
void StackInit(Stack* ps) {
    assert(ps); // 必须检测ps不为空
    ps->array = (DataType*)malloc(sizeof(DataType) * 3);
    if (NULL == ps->array) perror("malloc失败");
    ps->capacity = 3;
    ps->size = 0;
}

// 入栈:需传递Stack*和数据
void StackPush(Stack* ps, DataType data) {
    assert(ps);
    // 扩容(简化)
    if (ps->size == ps->capacity) {
        ps->array = (DataType*)realloc(ps->array, ps->capacity * 2 * sizeof(DataType));
        ps->capacity *= 2;
    }
    ps->array[ps->size++] = data;
}

int main() {
    Stack s;
    StackInit(&s); // 手动传地址
    StackPush(&s, 1);
    printf("栈顶:%d\n", s.array[s.size - 1]); // 输出1
    return 0;
}

(2)C++ 实现(数据与方法封装)

cpp 复制代码
#include <iostream>
#include <cstdlib>
#include <cassert>
using namespace std;

typedef int DataType;
class Stack {
public:
    // 初始化:无需传指针,编译器自动传递this
    void Init() {
        _array = (DataType*)malloc(sizeof(DataType) * 3);
        if (NULL == _array) perror("malloc失败");
        _capacity = 3;
        _size = 0;
    }

    // 入栈:直接访问成员变量,无需传指针
    void Push(DataType data) {
        CheckCapacity();
        _array[_size++] = data;
    }

    // 取栈顶:直接返回,无需传指针
    DataType Top() {
        assert(_size > 0);
        return _array[_size - 1];
    }

private:
    // 扩容:私有函数,隐藏实现细节
    void CheckCapacity() {
        if (_size == _capacity) {
            _array = (DataType*)realloc(_array, _capacity * 2 * sizeof(DataType));
            _capacity *= 2;
        }
    }

    // 成员变量:私有,防止误修改
    DataType* _array;
    int _capacity;
    int _size;
};

int main() {
    Stack s;
    s.Init(); // 直接调用,无需传地址
    s.Push(1);
    cout << "栈顶:" << s.Top() << endl; // 输出1
    return 0;
}

9.2 核心差异对比

|-------|------------------------|--------------------|
| 特性 | C 语言实现 | C++ 实现 |
| 数据与方法 | 分离(结构体存数据,独立函数操作) | 封装(类内结合) |
| 参数传递 | 手动传结构体指针,需检测非空 | 自动传 this 指针,用户无需关心 |
| 安全性 | 成员变量可直接修改(如s.size=100) | 成员变量私有,仅通过接口访问 |
| 实现细节 | 扩容等函数对外暴露 | 私有函数隐藏细节,仅暴露必要接口 |

9.3 注意点

  • C++ 的封装让代码更简洁、安全,减少指针操作错误;
  • C++ 兼容 C 语言写法,但开发中优先用类的封装特性;
  • 面试小提示:"C++ 相比 C 语言实现 Stack 的优势?"------ 答:封装数据和方法、自动传递 this 指针、隐藏实现细节、提高代码安全性和可读性。

十、学习总结与建议

  • 核心逻辑:本章围绕 "封装" 展开,类是 C++ 封装的核心,通过 "数据 + 方法" 结合、访问限定符控制权限,让代码更安全易维护;
  • 重点突破:
    • 类的定义与实例化(类是模板,对象是实例);
    • 对象大小计算(成员变量 + 内存对齐,空类 1 字节);
    • this 指针(隐含传递、特性、面试题);
    • 访问限定符与封装(struct 和 class 的区别);
  • 学习方法:
    • 多敲代码:每个示例(尤其是错误示例)都要编译运行,观察报错信息;
    • 对比学习:通过 C 和 C++ 实现 Stack 的差异,体会面向对象优势;
    • 聚焦面试:内存对齐、this 指针、struct 与 class 区别是高频考点;
  • 避坑清单:
    • 类定义结尾不要漏分号;
    • 类外定义成员函数必须加类名::
    • 成员变量命名要区分形参(如加_);
    • 空类大小为 1 字节,非静态成员函数不占对象空间。

相关推荐
!停1 小时前
数据结构时间复杂度
c语言·开发语言·算法
王老师青少年编程1 小时前
2025信奥赛C++提高组csp-s复赛真题及题解:社团招新
c++·真题·csp·信奥赛·csp-s·提高组·复赛
一叶星殇1 小时前
.NET 6 NLog 实现多日志文件按业务模块拆分的实践
开发语言·.net
橘子师兄1 小时前
C++AI大模型接入SDK—Ollama本地接入Deepseek
c++·人工智能·后端
程序猿编码1 小时前
深入浅出Linux内核级防火墙:IP/端口黑白名单的高性能实现
linux·c语言·c++·tcp/ip·内核
lead520lyq2 小时前
Golang GPRC流式传输案例
服务器·开发语言·golang
xyq20242 小时前
《C 经典100例》
开发语言
不染尘.2 小时前
二分算法(优化)
开发语言·c++·算法
只是懒得想了2 小时前
Go语言ORM深度解析:GORM、XORM与entgo实战对比及最佳实践
开发语言·数据库·后端·golang