当前位置: 首页 > news >正文

C++ 类与对象(上)笔记(整理与补充)

C++ 类与对象核心笔记(整理与补充)

一、引言:类与对象的核心地位

C++ 作为面向对象编程语言(OOP),其核心思想围绕 “类” 与 “对象” 展开。类是对现实世界中一类事物的抽象描述(模板 / 图纸),对象是类的具体实例(实体)。本笔记系统梳理类与对象的定义、封装、内存模型、访问控制等核心知识点,结合代码示例与细节补充,夯实 OOP 基础。

二、类的基础定义与文件组织规范

2.1 类的构成要素

类是 “成员变量”(描述对象属性 / 状态)与 “成员方法”(描述对象行为 / 操作)的集合,是封装思想的直接体现。

2.2 类的声明与定义的文件拆分原则

为保证代码模块化与可维护性,C++ 中类的声明定义通常拆分到不同文件:

  • 声明(Declaration):放在.h(头文件)中,仅告知编译器 “类的结构”(包含哪些成员变量、成员方法的签名),不涉及具体实现。
  • 定义(Definition):放在.cpp(源文件)中,实现.h中声明的成员方法(填充函数逻辑)。
补充:头文件保护(防止重复包含)

用户未提及头文件重复包含问题,此处补充:.h文件需添加 “头 guard” 或#pragma once,避免因多次包含导致编译错误。示例如下:

// Person.h(头文件,类的声明)
#ifndef PERSON_H  // 头 guard 开始(也可使用 #pragma once)
#define PERSON_H#include <string>  // 包含成员变量/方法依赖的头文件// 类的声明:仅描述结构,不实现成员函数
class Person {
public:// 成员变量声明(属性:姓名、性别、年龄)std::string _name;std::string _gender;int _age;// 成员方法声明(行为:打印个人信息)void PrintPersonInfo();
};#endif  // PERSON_H  // 头 guard 结束
// Person.cpp(源文件,类的定义)
#include "Person.h"  // 包含对应头文件,关联类声明
#include <iostream>  // 依赖的输入输出头文件// 成员方法的类外定义:通过::(作用域解析符)指定所属类
void Person::PrintPersonInfo() {// 访问类的成员变量,实现打印逻辑std::cout << "姓名:" << _name << ",性别:" << _gender << ",年龄:" << _age << std::endl;
}

三、封装思想与访问限定符

3.1 封装的核心作用

封装是 OOP 三大特性(封装、继承、多态)之首,核心实现两大目标:

  1. 数据与行为的整合:将描述对象的 “数据(成员变量)” 与操作数据的 “行为(成员方法)” 绑定在类内部,使对象成为逻辑完整的独立单元。
  2. 选择性暴露接口:通过访问控制,隐藏类的内部实现细节(如核心数据),仅对外暴露安全的操作接口(如数据查询 / 修改方法),保证数据安全性与使用规范性。

3.2 三种访问限定符的功能

C++ 通过publicprotectedprivate三个关键字控制类成员的 “对外可见性”,具体功能如下:

访问限定符访问范围核心用途
public类内、类外、子类均可访问定义对外暴露的接口(如成员方法、公共常量)
protected类内、子类可访问,类外不可访问定义子类需继承的成员(兼顾隐藏与继承需求)
private仅类内可访问,类外、子类均不可访问定义类的核心隐私数据(如成员变量)
说明:
  • 通常成员变量默认设为private(避免类外直接修改,保证数据完整性),通过public成员方法间接操作(如SetAge(int age)设置年龄,GetAge()获取年龄)。
  • protected的特殊性需结合 “继承” 理解:子类可访问父类的protected成员,但外部代码无法访问,后续继承章节会详细展开。

3.3 访问限定符的生效范围

访问限定符的生效规则:从限定符出现的位置开始,直到下一个访问限定符出现或类定义结束为止,期间所有成员均遵循当前限定符的访问规则。

示例代码(含注释):

class Student {
// 第一个访问限定符:public
public:// 以下成员均为public(直到下一个限定符private出现)std::string _studentId;  // 学号(对外可访问,如查询学号)void ShowStudentId() {   // 打印学号(对外接口)std::cout << "学号:" << _studentId << std::endl;}// 第二个访问限定符:private
private:// 以下成员均为private(直到类定义结束)std::string _name;  // 姓名(核心数据,类外不可直接访问)int _score;         // 分数(核心数据,类外不可直接修改)// private成员方法:仅类内调用(如校验分数合法性)bool IsScoreValid(int score) {return score >= 0 && score <= 100;}// 第三个访问限定符:public(若后续有成员,需重新指定)
public:// 对外接口:设置分数(通过private方法校验,保证数据合法)void SetScore(int score) {if (IsScoreValid(score)) {_score = score;} else {std::cout << "分数非法!" << std::endl;}}
};

四、C 与 C++ 的 struct 差异及 C++ 中 class 与 struct 的区别

4.1 C 语言的 struct 特性

C 语言的 struct 仅作为 “纯数据容器”,不支持封装行为,核心特性如下:

  1. 仅能包含成员变量(如 int、指针等),不能包含函数。
  2. 使用自身类型的指针时,必须显式添加struct关键字(C 中 struct 名不能单独作为类型名)。

示例代码(C 语言 struct,含注释):

// C语言的struct:仅存储数据,无成员函数
struct ListNode_C {int _val;                  // 数据域:节点值struct ListNode_C* _next;  // 指针域:下一个节点地址(必须加struct)struct ListNode_C* _prev;  // 指针域:上一个节点地址(必须加struct)
};// C语言中使用struct:需通过struct ListNode_C定义变量
void C_Struct_Example() {struct ListNode_C node1;  // 定义struct变量,必须加structnode1._val = 10;          // 直接访问成员变量(C中struct成员默认公开)node1._next = NULL;
}

4.2 C++ 的 struct 特性

C++ 的 struct 兼容 C 语言用法,同时具备 “类(class)的部分能力”,核心特性如下:

  1. 兼容 C:可作为纯数据容器,仅包含成员变量。
  2. 扩展功能:支持包含成员函数(实现数据与行为的封装),可直接用 struct 名作为类型名(无需加 struct)。

示例代码(C++ 的 struct,含注释):

// C++的struct:支持成员变量+成员函数,实现封装
struct ListNode_CPP {int _val;                  // 数据域:节点值ListNode_CPP* _next;       // 指针域:直接用struct名作为类型名(无需加struct)ListNode_CPP* _prev;       // 指针域:无需加struct// 成员函数:初始化节点(封装操作数据的行为)void InitNode(int val) {_val = val;    // 成员函数内部访问成员变量_next = NULL;_prev = NULL;}// 成员函数:打印节点值(对外暴露的接口)void PrintVal() {std::cout << "节点值:" << _val << std::endl;}
};// C++中使用struct:直接用struct名定义变量,无需加struct
void CPP_Struct_Example() {ListNode_CPP node2;  // 无需加struct,直接作为类型名node2.InitNode(20);  // 调用成员函数初始化node2.PrintVal();    // 调用成员函数打印(输出:节点值:20)
}

4.3 C++ 中 class 与 struct 的核心差异

C++ 中 class 与 struct 均能定义 “类”,唯一核心差异是默认访问权限,其他特性(如继承、多态)完全一致:

关键字默认访问权限成员变量 / 函数默认可见性适用场景
classprivate类外不可直接访问默认成员定义需严格隐藏内部细节的类(如业务对象)
structpublic类外可直接访问默认成员定义简单数据结构(如链表节点)或兼容 C 代码
补充:
  • 无论使用class还是struct,均可显式添加public/protected/private来控制访问权限,默认权限仅影响未指定限定符的成员。
  • 示例:用 struct 定义类并显式指定权限,与 class 行为一致:
    struct Person_Struct {
    private:  // 显式指定private,成员变量默认不可访问std::string _name;
    public:   // 显式指定public,成员方法对外可见void SetName(const std::string& name) {_name = name;}
    };
    

五、声明与定义的区别(含类成员函数)

5.1 声明(Declaration)的本质

声明是 “向编译器承诺某个实体的存在”,仅告知实体的 “名称与签名”,不分配内存或填充实现逻辑。核心特点:

  • 不包含具体实现(如函数无函数体,变量无初始化)。
  • 可多次声明(如函数声明可在多个文件中出现,只要签名一致)。

示例(函数声明与变量声明):

// 函数声明:仅告知函数名、参数类型、返回值类型,无实现
void add(int a, int b);  // 声明“存在一个add函数,接收两个int,返回void”// 变量声明:用extern告知“变量在其他文件定义”,不分配内存
extern int global_num;  // 声明“global_num是int类型,在其他文件定义”

5.2 定义(Definition)的本质

定义是 “将声明的承诺落地”,分配内存(变量)或填充实现逻辑(函数),核心特点:

  • 包含具体实现(函数有函数体,变量有内存分配,可初始化)。
  • 同一作用域内仅能定义一次(避免重复分配资源,即 “单定义规则 ODR”)。

示例(函数定义与变量定义):

// 函数定义:实现add函数的逻辑,分配代码区内存
void add(int a, int b) {std::cout << "两数之和:" << a + b << std::endl;  // 具体实现
}// 变量定义:分配内存(栈/全局区),可初始化
int global_num = 10;  // 定义global_num,分配内存并初始化为10

5.3 类成员函数的两种定义方式

类成员函数的定义分为 “类内定义” 与 “类外定义”,均需先在类内声明(或直接在类内定义即包含声明)。

方式 1:类内定义(声明 + 定义合一)
  • 直接在类的 {} 内部编写成员函数的实现,此时函数默认被编译器视为inline(内联函数,适合简单逻辑,避免函数调用开销)。
  • 示例(Person 类内定义成员函数):
    class Person {
    public:std::string _name;int _age;// 类内定义成员函数:声明与定义合一,默认inlinevoid ShowInfo() {// 直接访问类内成员变量,实现打印逻辑std::cout << "姓名:" << _name << ",年龄:" << _age << std::endl;}
    };
    
方式 2:类外定义(声明与定义分离)
  • 类内仅声明成员函数(告知函数签名),类外通过::(作用域解析符)指定函数所属类,补充实现逻辑。
  • 必须包含对应类的头文件,确保编译器能关联声明与定义。
  • 示例(Person 类外定义成员函数,与 2.2 节文件组织一致):
    // Person.h(类内声明)
    class Person {
    public:std::string _name;void PrintPersonInfo();  // 仅声明,无实现
    };// Person.cpp(类外定义)
    #include "Person.h"
    #include <iostream>// 类外定义:通过Person::指定PrintPersonInfo属于Person类
    void Person::PrintPersonInfo() {std::cout << "姓名:" << _name << std::endl;  // 实现逻辑
    }
    
补充:成员函数声明与定义的一致性要求
  • 函数签名(参数类型、参数个数、参数顺序、const 修饰(若有))必须完全一致,否则编译器视为 “重载函数”,若未找到匹配声明则报错。
  • 示例:若类内声明为void SetAge(int age),类外定义为void Person::SetAge(double age),则编译报错(签名不匹配)。

六、类与对象的关系(抽象与实例)

6.1 类与对象的本质区别

类与对象是 “抽象模板” 与 “具体实例” 的关系,类比现实世界:

  • 类(Class):抽象描述一类事物的 “共性”(属性 + 行为),无具体实体,不占用内存。例如 “汽车类” 描述汽车的属性(品牌、颜色)和行为(启动、刹车)。
  • 对象(Object):类的 “实例化产物”,具备类描述的所有属性与行为,占用实际内存。例如 “张三的红色特斯拉 Model 3” 是 “汽车类” 的一个对象。

6.2 代码层面的类与对象实现

步骤 1:定义类(抽象模板)
#include <string>
#include <iostream>// 定义Person类(抽象模板):描述“人”的共性
class Person {
public:// 成员变量(属性):描述对象的状态std::string name;  // 姓名int age;           // 年龄// 成员函数(行为):描述对象的操作void show() {// 打印对象的属性,所有Person对象共用此逻辑std::cout << name << " " << age << std::endl;}
};
步骤 2:创建对象(实例化)

通过 “类名 + 对象名” 在栈上创建对象,或通过new在堆上创建对象(用户未提及堆上创建,补充此方式)。

int main() {// 方式1:栈上创建对象(p1):自动分配/释放内存,作用域结束后销毁Person p1;  // p1是Person类的对象(实例)p1.name = "张三";  // 给p1的成员变量赋值(每个对象的属性独立)p1.age = 20;p1.show();  // 调用p1的成员函数(执行show逻辑,输出:张三 20)// 方式2:堆上创建对象(p2):手动分配/释放内存,需用delete销毁Person* p2 = new Person();  // 用new创建对象,返回指向对象的指针p2->name = "李四";          // 堆对象通过->访问成员(指针访问语法)p2->age = 25;p2->show();                 // 调用堆对象的成员函数(输出:李四 25)delete p2;                  // 手动释放堆内存,避免内存泄漏p2 = NULL;                  // 指针置空,避免野指针return 0;
}

6.3 核心特性:成员函数的共用性

  • 成员变量:每个对象独立存储,占用对象的内存(如 p1 的 name 和 p2 的 name 存储在不同地址,值可不同)。
  • 成员函数:所有同类型对象共用一份代码,存储在代码区(而非对象内存中),避免重复存储导致的内存浪费。
  • 补充:通过sizeof(对象)可验证:对象大小仅包含成员变量的大小(含内存对齐填充),与成员函数无关。例如sizeof(Person) = sizeof(std::string) + sizeof(int)(需考虑内存对齐)。

七、对象的内存模型(含内存对齐)

7.1 对象的内存构成

对象的内存仅存储非静态成员变量,成员函数、静态成员(静态变量、静态函数)均存储在全局代码区 / 数据区,不占用对象内存。核心原因:

  • 成员变量是 “对象专属”:每个对象的成员变量值不同(如学生 A 和 B 的分数不同),需独立存储。
  • 成员函数是 “类共用”:所有对象的成员函数逻辑一致(如计算分数的逻辑),共用一份代码即可。
补充:空类的内存大小

用户未提及空类(无任何成员变量 / 成员函数的类),补充:空类的大小为1 字节(编译器为其分配 1 字节内存,用于区分不同空类对象的地址,避免所有空类对象地址相同)。

// 空类示例
class EmptyClass {};int main() {std::cout << sizeof(EmptyClass) << std::endl;  // 输出:1(而非0)return 0;
}

7.2 内存对齐:编译器的地址调整策略

7.2.1 内存对齐的定义

内存对齐是编译器对变量存储地址的强制调整规则:变量的起始地址必须是其 “自身大小” 的整数倍(如 int(4 字节)的起始地址必须是 4 的倍数,double(8 字节)的起始地址必须是 8 的倍数)。

7.2.2 内存对齐的核心原因
  1. 提升硬件访问效率:CPU 读取内存时按 “固定块大小”(如 4 字节、8 字节)读取。若变量对齐,CPU 仅需 1 次读取即可获取数据;若未对齐,需 2 次读取 + 数据拼接,效率显著降低。
  2. 兼容硬件限制:部分嵌入式芯片、旧 CPU 不支持 “非对齐地址访问”,强制非对齐会导致程序崩溃。
7.2.3 类对象内存对齐的计算步骤

类对象的大小 = 所有非静态成员变量大小之和 + 填充字节(padding)(编译器自动插入,用于满足对齐规则),计算分两步:

步骤 1:单个成员变量的 “偏移量对齐”

每个成员变量的 “偏移量”(相对于对象起始地址的字节数)必须是其自身大小的整数倍,若不满足则插入填充字节。

步骤 2:整个类对象的 “总大小对齐”

类对象的总大小必须是 “所有成员变量中最大大小” 的整数倍,若不满足则在末尾插入填充字节。

示例:类 A 的内存对齐计算(含注释)
// 定义类A,包含char、int、double三种成员变量
class A {
public:char c;   // 大小1字节,自身大小=1int i;    // 大小4字节,自身大小=4double d; // 大小8字节,自身大小=8
};int main() {// 计算类A对象的大小,按内存对齐规则分析:// 步骤1:单个成员偏移量对齐// - c的偏移量:0(0是1的整数倍,无需填充),占用0~0字节// - i的自身大小=4,偏移量需是4的整数倍:当前偏移量为1(c占1字节),需插入3字节填充(1→4),i占用4~7字节// - d的自身大小=8,偏移量需是8的整数倍:当前偏移量为8(i占4字节,4+4=8),无需填充,d占用8~15字节// 步骤2:总大小对齐// 所有成员最大大小=8(double),当前总大小=1(c)+3(填充)+4(i)+8(d)=16字节,16是8的整数倍,无需末尾填充std::cout << sizeof(A) << std::endl;  // 输出:16(而非1+4+8=13)return 0;
}
补充:内存对齐的编译器控制

用户未提及如何调整对齐规则,补充:可通过编译器选项或预处理指令修改默认对齐系数(如默认对齐系数为 8,可改为 4):

  • GCC 编译器:通过-fpack-struct=n选项(n 为对齐系数,如g++ -fpack-struct=4 test.cpp)。
  • VS 编译器:通过#pragma pack(n)指令(如#pragma pack(4)设置对齐系数为 4,#pragma pack()恢复默认)。

示例(修改对齐系数为 4):

#pragma pack(4)  // 设置对齐系数为4
class A {
public:char c;   // 1字节double d; // 8字节(自身大小8,但对齐系数为4,偏移量需是4的整数倍)
};
#pragma pack()  // 恢复默认对齐int main() {// 分析:// c偏移量0(1的倍数),占用0~0// d的偏移量需是4的倍数:当前偏移量1,插入3字节填充(1→4),d占用4~11// 总大小=1+3+8=12,最大成员大小8,但对齐系数4,12是4的倍数,总大小12std::cout << sizeof(A) << std::endl;  // 输出:12return 0;
}

八、this 指针:成员函数的隐式参数

8.1 this 指针的本质

this 指针是编译器为非静态成员函数隐式添加的 “隐藏参数”,其类型为 “类名* const”(指向当前类对象的常量指针,不能修改指向,但可修改指针指向的对象内容),核心作用:标识 “当前调用成员函数的对象”,使成员函数能精准访问当前对象的成员变量。

补充:this 指针的 const 属性
  • 普通成员函数的 this 指针:类名* const this(指向不可改,对象内容可改)。
  • const 成员函数的 this 指针:const 类名* const this(指向不可改,对象内容也不可改,用于保证函数不修改对象状态),用户未提及,补充示例:
    class Person {
    public:std::string _name;int _age;// const成员函数:this指针为const Person* const,不能修改对象成员void ShowInfo() const {std::cout << _name << " " << _age << std::endl;  // 仅访问,不修改,合法// _age = 30;  // 错误:const成员函数不能修改对象成员}
    };
    

8.2 this 指针的工作机制(编译器隐式处理)

程序员无需显式声明或传递 this 指针,编译器在编译阶段自动完成以下操作:

步骤 1:成员函数参数隐式添加 this 指针

程序员编写的成员函数:

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

编译器处理后(隐式添加 this 参数):

// 编译器自动添加this指针参数,程序员不可见
void Date::Init(Date* this, int year, int month, int day) {this->_year = year;  // 隐式通过this访问成员变量this->_month = month;this->_day = day;
}
步骤 2:调用成员函数时隐式传递对象地址

程序员编写的调用代码:

Date d1;
d1.Init(2024, 5, 20);  // 调用d1的Init函数

编译器处理后(隐式传递 d1 的地址给 this):

Date d1;
// 隐式将&d1作为this参数传递
d1.Init(&d1, 2024, 5, 20);
步骤 3:成员访问隐式转换为 this-> 成员

程序员编写的成员访问:

void Date::Print() {std::cout << _year << "-" << _month << "-" << _day << std::endl;
}

编译器处理后(隐式添加 this->):

void Date::Print(Date* this) {// 隐式通过this指针访问当前对象的成员变量std::cout << this->_year << "-" << this->_month << "-" << this->_day << std::endl;
}

8.3 this 指针的存储位置

  • 理论上:this 指针作为函数形参,应存储在栈区(函数形参默认在栈上分配)。
  • 实际实现:为提升效率,主流编译器(如 VS)通过寄存器(ecx 寄存器) 传递 this 指针,而非栈区(减少栈操作开销)。
  • 注意:this 指针不能被用户显式修改(因类型是类名* const),也不能在成员函数中显式声明 this 指针。

九、空指针调用成员函数的行为分析

空指针(NULL)指向 “无有效内存的地址”,调用成员函数时的行为取决于函数是否 “访问成员变量”(即是否依赖 this 指针)。

9.1 示例代码(含详细注释)

#include <iostream>
using namespace std;class A {
public:// 成员函数1:访问成员变量(依赖this指针)void PrintA() {// 编译器会转换为:cout << this->_a << endl;// 若this为NULL,解引用NULL会导致程序崩溃cout << _a << endl;}// 成员函数2:不访问成员变量(不依赖this指针)void Show() {// 仅执行输出逻辑,无需访问对象成员,不依赖this指针cout << "Show()" << endl;}private:int _a;  // 成员变量:PrintA函数依赖此变量
};int main() {A* p = NULL;  // 定义空指针p,不指向任何有效对象// 情况1:p->PrintA(); —— 程序崩溃// 原因:PrintA访问成员变量_a,需通过this指针(this = p = NULL)// 解引用NULL指针(this->_a)是未定义行为,导致程序崩溃// p->PrintA();  // 取消注释后运行,程序崩溃// 情况2:p->Show(); —— 正常运行// 原因:Show函数不访问任何成员变量,无需依赖this指针// 成员函数存储在代码区,调用时仅需找到函数地址,无需访问对象内存p->Show();  // 输出:Show(),正常运行return 0;
}

9.2 核心结论与补充注意事项

  1. 崩溃条件:若成员函数访问成员变量(依赖 this 指针),空指针调用会因 “解引用 NULL 指针” 导致程序崩溃(未定义行为)。
  2. 正常条件:若成员函数不访问成员变量(不依赖 this 指针),空指针调用可能正常运行(但仍不推荐)。
  3. 补充注意事项
    • 空指针调用成员函数属于 “未定义行为”(C++ 标准未规定其行为),即使当前正常运行,也可能因编译器版本、平台变化导致崩溃。
    • 实际开发中应避免空指针调用成员函数,需先判断指针是否非 NULL(如if (p != NULL) p->Show();)。

十、补充:类的静态成员

用户未提及静态成员,静态成员是类的重要组成部分,补充如下:

10.1 静态成员的定义

静态成员(静态成员变量、静态成员函数)属于 “类本身”,而非单个对象,所有对象共用静态成员,存储在全局数据区(而非对象内存)。

10.2 静态成员变量

  • 特性

    1. 需在类内声明(加static关键字),类外定义(分配内存,仅一次)。
    2. 所有对象共用一份,修改一个对象的静态成员变量,所有对象均可见。
    3. 可通过 “类名::静态变量名” 或 “对象。静态变量名” 访问(推荐前者,明确属于类)。
  • 示例代码

    class Student {
    public:std::string _name;static int _studentCount;  // 类内声明静态成员变量:学生总数
    };// 类外定义静态成员变量:必须加类名::,分配全局数据区内存
    int Student::_studentCount = 0;int main() {Student s1;Student s2;Student::_studentCount++;  // 通过类名访问,学生总数+1(变为1)s2._studentCount++;        // 通过对象访问,学生总数+1(变为2)// 所有对象共用静态变量,输出均为2cout << Student::_studentCount << endl;  // 输出:2cout << s1._studentCount << endl;        // 输出:2return 0;
    }
    

10.3 静态成员函数

  • 特性

    1. 类内声明(加static关键字),类外定义(无需加static)。
    2. 无 this 指针(因属于类,不依赖对象),故不能访问非静态成员变量 / 函数(需通过对象指针 / 引用访问)。
    3. 可通过 “类名::静态函数名” 或 “对象。静态函数名” 访问。
  • 示例代码

    class Student {
    public:std::string _name;static int _studentCount;// 静态成员函数:无this指针,不能访问非静态成员static void ShowStudentCount() {cout << "学生总数:" << _studentCount << endl;  // 可访问静态成员// cout << _name << endl;  // 错误:不能访问非静态成员(无this指针)}
    };int Student::_studentCount = 0;int main() {Student::_studentCount = 3;Student::ShowStudentCount();  // 通过类名调用,输出:学生总数:3Student s;s.ShowStudentCount();         // 通过对象调用,输出:学生总数:3return 0;
    }
    

十一、总结

本笔记围绕 C++ 类与对象的核心知识点展开,涵盖类的定义与文件组织、封装与访问控制、class 与 struct 差异、声明与定义、类与对象的抽象实例关系、对象内存模型与内存对齐、this 指针机制、空指针调用问题及静态成员补充。核心逻辑遵循 “从抽象到具体、从语法到原理”,结合代码示例与细节补充,可作为 OOP 基础的系统参考。后续需进一步学习继承、多态等特性,以完善面向对象编程知识体系。

http://www.dtcms.com/a/465221.html

相关文章:

  • 基于Python 实现企业搜索系统(信息检索)
  • 学习爬虫第四天:多任务爬虫
  • 专注大连网站建设长沙网站设计咨询电话
  • 网站备案编号查询做网站的语言版本
  • 预训练基础模型简介
  • 【笔记】WPF中如何的动态设置DataGridTextColumn是否显示
  • 告别手动复制,API助您完成电商数据获取数据分析店铺搬家
  • 软件工程的核心原理与实践
  • LeetCode 394. 字符串解码(Decode String)
  • Spring Bean耗时分析工具
  • 济南可信网站网站开发命名规范
  • 应用案例丨3D工业相机如何实现「焊接全工序守护」
  • 网站接广告网站可以叫做系统吗
  • 应用层协议之Telnet协议
  • 科技赋能成长,小康AI家庭医生守护童真
  • 芯谷科技--D7005高效高压降压型DC-DC转换器
  • 玻尿酸:从天然分子到科技美学的全面解析
  • # 3.1.8<3.2.0<3.3.1,Apache DolphinScheduler集群升级避坑指南
  • 微算法科技(NASDAQ:MLGO)基于任务迁移的弹性框架重塑动态扩缩容,赋能边缘智能计算
  • 卡盟网站怎么做图片wordpress换网址插件
  • 【汽车篇】基于深度学习的门盖自动装配系统:汽车制造装配的革新力量
  • 乐迪信息:基于AI算法的煤矿作业人员安全规范智能监测与预警系统
  • 英文电商网站建设泛微oa办公系统教程
  • Windows环境搭建:PostGreSQL+PostGIS安装教程
  • SQL COUNT() 函数详解
  • 中山网站设计收费标准wordpress 右边栏
  • 坦桑尼亚网站域名后缀一个虚拟主机可以放几个网站
  • 从大模型到轻量级部署:知识蒸馏优化技术
  • 速通ACM省铜第二十一天(补) 赋源码(共现的数)
  • 自用,正点Linux虚拟机系统文件概况