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

C++继承 ---- 继承是面向对象三大特性之一【好处:可以减少重复的代码】

目录

一、前言:继承技术的引入 

二、继承的基本语法 

2.1. 基本语法

2.2. 继承示例

三、三种继承方式【公共继承、保护继承、私有继承】

2.1 基本概念 

2.2 三种继承方式的影响 

 2.3 为什么通常使用 public 继承?

2.4 class的默认继承方式:private继承

四、继承中的对象模型

📌 继承成员的归属情况

1️⃣ 属于子类对象的成员

2️⃣ 不属于子类对象的成员

🔬 代码验证

🔎 结果分析

💡 结论

✅ 属于子类对象的:

❌ 不属于子类对象的:

五、继承中的构造和析构顺序

六、继承同名成员处理方式 

6.1 示例:非静态成员变量情况下 

6.2 示例:非静态成员函数情况下

6.3 示例:静态成员变量情况下

6.3.1 通过对象访问 

6.3.2 通过类名来访问

6.4 示例:静态成员函数情况下

6.4.1 通过对象访问 

6.4.2 通过类名来访问 

6.5 总结

七、多继承语法【可以认多个爹】

 7.1 多继承的基本语法

🚨 7.2. 多继承的命名冲突【作用域解析符 :: 解决命名冲突】

💢 7.3. 菱形继承问题(Diamond Problem)【虚继承 virtual 解决菱形继承】

7.3.1 菱形继承示例

7.3.2 解决方案:使用虚继承

7.3.3 虚继承解决菱形继承的底层原理 

八、Python中的 super() 等效于 Base::method() 调用


一、前言:继承技术的引入 

 有些类与类之间存在特殊的关系,如下图中所示:

从这幅图可以直观地看出继承在面向对象编程(OOP)中的应用。

  • 最顶层是“动物”类(基类):所有猫和狗的共同特性(如生命体、能移动等)都可以定义在这个类中。
  • 第二层是“猫”和“狗”类(派生类):它们继承了“动物”的共性,同时可以添加各自独特的行为,比如猫会“喵喵叫”,狗会“汪汪叫”。
  • 第三层是具体的猫和狗品种:比如加菲猫、布偶猫、哈士奇、德牧等。它们不仅拥有“猫”或“狗”的特性,还可以进一步细化,比如加菲猫的扁脸、哈士奇的“二哈”性格等。

结合继承来看:

  • 代码复用:比如所有猫科动物的行为可以定义在“猫”类中,所有狗的行为可以定义在“狗”类中,而不用为每个品种重复编写。
  • 层级清晰:继承关系清晰地表达了从一般到具体的层次关系,使代码更易维护和拓展。
  • 便于扩展:如果未来需要新增动物类别(比如“鸟”),只需继承“动物”类,而不影响现有结构。

这幅图很好地体现了继承的本质:将共性上移,个性下放,减少重复,提高代码的组织性和可维护性。 😊

对上述内容的同等专业语言描述: 

        在定义类时,我们常常会遇到这样的情况:下级别的成员不仅继承了上一级的共性,还具备自身的特性。此时,我们可以借助继承这一技术,减少重复代码,提高代码的复用性。

        继承是面向对象编程(OOP)的核心概念之一,它使子类(派生类)能够直接复用父类(基类)的属性和方法,同时可以根据自身需求进行扩展或重写。这不仅有助于提升代码的组织性和可维护性,还能让程序结构更加清晰,便于后续扩展和优化。

再举一个实际项目的继承例子:

在网站开发中,通常会有公共的头部、底部、侧边栏,这些部分在多个页面中是相同的,而页面的主要内容(中心区域)是不同的。我们可以使用继承来避免重复代码,让子类只关注自己的“独特内容”。

例如我们打开网页:人工智能开发基础,人工智能开发教程,人工智能开发学习就来黑马程序员

公共的头部分:

公共的侧边栏部分: 

公共的底部分: 

 不同的中心区域:

  • 人工智能开发:

  • C/C++: 

我们可以使用继承来避免重复代码,让子类只关注自己的“独特内容”。 

  • 基类(父类):WebPage
    负责定义通用部分(头部、底部、侧边栏)。
  • 子类(派生类):HomePageAboutPageContactPage
    只需要专注于中心内容,而公共部分由父类提供

派生类中的成员包含两大部分:
一类是从基类继承过来的,一类是自己增加的成员。
从基类继承过来的表现其共性,而新增的成员体现了其个性。

二、继承的基本语法 

在 C++ 中,继承(Inheritance) 允许子类(派生类)继承父类(基类)的成员变量和方法,从而提高代码复用性和可维护性。


2.1. 基本语法

class 父类名 {
public:父类名(参数) {// 构造函数}void 方法() {cout << "这是父类的方法" << endl;}
};// 子类继承父类
class 子类名 : public 父类名 {
public:子类名(参数) : 父类名(参数) {}  // 调用父类构造函数
};

2.2. 继承示例

#include <iostream>
using namespace std;// 定义父类 Animal
class Animal {
public:string name;// 构造函数Animal(string name) {this->name = name;}// 父类方法void makeSound() {cout << "动物在发出声音" << endl;}
};// 子类 Dog 继承 Animal
class Dog : public Animal {
public:// 构造函数,调用父类构造函数Dog(string name) : Animal(name) {}// 重写父类方法void makeSound() {cout << name << ":汪汪!" << endl;}
};int main() {Dog dog("哈士奇");dog.makeSound();  // 输出:哈士奇:汪汪!return 0;
}

说明

  • Dog 继承了 Animal 的属性 name,并重写了 makeSound() 方法。
  • 子类构造函数 Dog(string name) : Animal(name) 显式调用了父类构造函数。

三、三种继承方式【公共继承、保护继承、私有继承】

2.1 基本概念 

在 C++ 中,class Child : [继承方式] Parent  指定了子类继承父类的方式,[继承方式] 决定了 父类成员在子类中的访问权限

C++ 提供三种继承方式:

  1. public 继承(常用)
  2. protected 继承
  3. private 继承

这三种继承方式会影响 父类的 publicprotected 成员子类中的访问权限

继承方式父类的 public 变成父类的 protected 变成父类的 private
public 继承仍然是 public仍然是 protected无法访问
protected 继承变成 protected仍然是 protected无法访问
private 继承变成 private变成 private无法访问

向高权限兼容!! 

2.2 三种继承方式的影响 

#include <iostream>
using namespace std;class Parent {
public:int pubVar;      // 公有成员
protected:int protVar;     // 受保护成员
private:int privVar;     // 私有成员(子类不可访问)
};// 1. public 继承
class ChildPublic : public Parent {
public:void show() {pubVar=10; // 父类中的公共权限成员 到子类中依然是公共权限protVar=10; // 父类中的受保护权限成员 到子类中依然是受保护权限// privVar=10; // ❌ 子类无法访问父类的 private 成员}
};// 2. protected 继承
class ChildProtected : protected Parent {public:void show() {pubVar=10; // 父类中的公共权限成员 到子类中为受保护权限protVar=10; // 父类中的受保护权限成员 到子类中依然是受保护权限// privVar=10; // ❌ 子类无法访问父类的 private 成员}
};// 3. private 继承
class ChildPrivate : private Parent {
public:void show() {pubVar=10; // 父类中的公共权限成员 到子类中是私有权限protVar=10; // 父类中的受保护权限成员 到子类中是私有权限// privVar=10; // ❌ 子类无法访问父类的 private 成员}
};int main() {ChildPublic obj1;cout << obj1.pubVar << endl;  // ✅ `public` 继承,外部可以访问 pubVar// cout << obj1.protVar;  // ❌ protected 成员仍然不可外部访问ChildProtected obj2;// cout << obj2.pubVar;  // ❌ `protected` 继承后,pubVar 变成 protected,外部无法访问ChildPrivate obj3;// cout << obj3.pubVar;  // ❌ `private` 继承后,pubVar 变成 private,外部无法访问return 0;
}

 2.3 为什么通常使用 public 继承?

public 继承遵循 “is-a” 关系,即 子类“是一种”父类,适用于 面向对象编程
public 继承后,子类对象 仍然可以使用父类的 public 成员,符合直觉。
privateprotected 继承会 改变访问权限,通常用于特殊情况,比如 代码封装限制子类访问

一般来说,如果子类应该 完全继承 父类的行为,使用 public 继承 是最佳选择。

2.4 class的默认继承方式:private继承

#include <iostream>
using namespace std;class Base {public:int m_A; // 基类中的公有成员变量
};class Derived : Base { // 省略了继承方式,默认是 private 继承public:// m_A=10; // 不是构造函数或成员函数中的赋值,而是非法的语句,不能这样写。void func(){m_A=10; // Derived 以 ptivate 继承方式继承了 Base,m_A 变量现在变成私有成员,外部无法访问}
};int main() {Base b;b.m_A; // 可以访问Derived d;d.m_A; // 编译❌:member "Base::m_A" (declared at line 6) is inaccessibleC/C++(265)return 0;
}

 错误原因

  • Derived 默认是 private 继承 Base,导致 Base::m_A 变成 privatemain() 中无法访问它。

四、继承中的对象模型

问题:从父类继承过来的成员,哪些属于子类对象中?

“在 C++ 中,从父类继承过来的非静态成员(变量/函数)会成为子类对象的一部分,而静态成员(变量/函数)、构造函数和析构函数并不属于子类对象。”

属于子类对象的

  1. 基类的非静态成员变量(无论是 publicprotected 还是 private,都存在于子类对象的内存中)
  2. 基类的非静态成员函数(但 private 成员函数不能在子类中访问)
  3. 基类的 protectedprivate 成员虽然不能被子类访问,但仍然在子类对象的内存布局中

不属于子类对象的

  1. 基类的静态成员变量(静态成员属于类,而不属于任何对象)
  2. 基类的构造函数和析构函数(它们只是控制对象的构造和销毁,不属于对象本身)
  3. 基类的静态成员函数(因为它们不依赖于具体对象)

💡 所以,继承只是让子类“拥有”了基类的非静态成员,但不意味着所有成员都属于子类对象! 🚀


📌 继承成员的归属情况

1️⃣ 属于子类对象的成员

  • 所有的非静态成员变量
  • 所有的非静态成员函数

💡 无论继承方式(public / protected / private),基类的非静态成员都会作为子类对象的一部分静态成员不会


2️⃣ 不属于子类对象的成员

  • 静态成员变量(Static Members)

    • 静态成员属于类本身,而不是对象。
    • 子类可以访问基类的静态成员,但静态成员不存储在子类对象中。
  • 基类的构造函数 & 析构函数

    • 构造函数不属于子类对象,但会在创建子类对象时执行。
    • 析构函数也不属于子类对象,但在销毁子类对象时会自动调用。
  • 私有继承和保护继承时的基类成员

    • privateprotected 继承时,基类的 publicprotected 成员的访问级别发生变化,但它们仍然存在于子类对象中。

🔬 代码验证

验证: 从父类继承过来的静态成员(变量/函数)不属于子类对象。

#include <iostream>
using namespace std;class Base {
public:int a;  // 非静态成员变量 -> 属于子类对象static int b;  // 静态成员变量 -> 不属于任何对象
};int Base::b = 10; // 初始化静态成员变量class Derived : public Base { // public 继承
public:int c; // 子类自己的成员变量
};int main() {Derived d;cout << "Size of Derived object: " << sizeof(d) << endl;cout << "Base::b (Static): " << Base::b << endl;return 0;
}// 输出:
// Size of Derived object: 8
// Base::b (Static): 10

🔎 结果分析

  • sizeof(d) 计算 Derived 对象的大小,包括了 Base 的非静态成员 a
  • Base::b 是静态成员,不属于 d,而是共享的

验证:基类中的public、protected、private成员是否被继承到子类中。

#include<iostream>class Base{public:int a;protected:int b;private:int c;
};class Derived:public Base{public:int d;
};int main(){// 打印子类实例大小【注意:类本身是不占用内存的,sizeof(Derived)本质是sizeof(Derived类的实例)】std::cout<<"size of Derived:"<<sizeof(Derived)<<std::endl; // 输出:size of Derived:16return 0;
}

💡 结论

属于子类对象的:

  1. 基类的非静态成员变量
  2. 基类的非静态成员函数
  3. 基类的 protected / private 继承时仍然保留的成员变量

不属于子类对象的:

  1. 静态成员变量
  2. 基类的构造函数 & 析构函数
  3. 基类的私有成员(子类无法访问,但仍然存储在对象中)

🎯 记住:继承会让基类的非静态成员成为子类对象的一部分,但静态成员和构造函数不会! 🚀


五、继承中的构造和析构顺序

子类继承父类后,当创建子类对象时,也会调用父类的构造函数

问题:父类和子类的构造和析构顺序是谁先谁后?
答案:父类构造-->子类构造-->子类析构-->父类析构

我们以父类与子类为例来说明构造顺序和析构顺序 ,示例如下:

#include<iostream>class Base{public:// 基类中的构造函数Base(){std::cout<<"调用基类中的构造函数"<<std::endl;}// 基类中的析构函数~Base(){std::cout<<"调用基类中的析构函数"<<std::endl;}};class Derived:public Base{public:Derived(){std::cout<<"调用子类中的构造函数"<<std::endl;}// 基类中的析构函数~Derived(){std::cout<<"调用子类中的析构函数"<<std::endl;}
};int main(){Derived d1; // 子类实例化return 0;
}
// 输出:(先有父亲再有儿子)
// 调用基类中的构造函数
// 调用子类中的构造函数
// 调用子类中的析构函数
// 调用基类中的析构函数

我们再增添一个孙子类来看看构造与析构顺序。 

#include<iostream>
// 父亲类
class Base{public:// 基类中的构造函数Base(){std::cout<<"调用Base类中的构造函数"<<std::endl;}// 基类中的析构函数~Base(){std::cout<<"调用Base类中的析构函数"<<std::endl;}
};
// 儿子类
class Derived:public Base{public:Derived(){std::cout<<"调用Derived类中的构造函数"<<std::endl;}// 基类中的析构函数~Derived(){std::cout<<"调用Derived类中的析构函数"<<std::endl;}
};// 孙子类
class grandDerived:public Derived{public:grandDerived(){std::cout<<"调用grandDerived类中的构造函数"<<std::endl;}// 基类中的析构函数~grandDerived(){std::cout<<"调用grandDerived类中的析构函数"<<std::endl;}
};int main(){grandDerived gd1; // 孙子类实例化return 0;
}
// 输出:(构造顺序:先有父亲再有儿子再有孙子,析构顺序:白发人送黑发人)
// 调用Base类中的构造函数
// 调用Derived类中的构造函数
// 调用grandDerived类中的构造函数
// 调用grandDerived类中的析构函数
// 调用Derived类中的析构函数
// 调用Base类中的析构函数

六、继承同名成员处理方式 

问题:当子类与父类出现同名的成员,如何通过子类对象,访问到子类或父类中同名的数据呢?

  • 访问子类同名成员直接访问即可
  • 访问父类同名成员需要加作用域 
  • 当子类与父类拥有同名的成员,子类会隐藏父类中同名成员,加父类作用域可以访问到父类中的成员。

6.1 示例:非静态成员变量情况下 

当子类中出现和父类同名的成员变量,子类的同名成员变量会隐藏掉父类中所有同名成员变量,如果想要通过子类对象访问到父类中被隐藏的同名成员变量,需要加父类作用域。  

#include<iostream>
// 父类
class Base{public:int m_A;Base(){ // 父类构造函数m_A=100;}
};
// 子类
class Derived:public Base{public:int m_A;Derived(){ // 子类构造函数m_A=200;}
};int main(){Derived d1; // 子类实例化std::cout<<"Derived 类中的 m_A = "<<d1.m_A<<std::endl; // 输出:Derived 类中的 m_A = 200 访问自身数据// 如果通过子类对象 访问到父类中与子类同名的成员,需要加父类作用域std::cout<<"Base 类中的 m_A = "<<d1.Base::m_A<<std::endl; // 输出:Base 类中的 m_A = 100return 0;
}

当子类中没有出现和父类同名的成员变量,可通过子类对象直接访问到父类中的成员变量。  

#include<iostream>
// 父类
class Base{public:int m_A=100;
};
// 子类
class Derived:public Base{public:
};int main(){Derived d1; // 子类实例化std::cout<<d1.m_A<<std::endl; // 输出:m_A = 100 return 0;
}

6.2 示例:非静态成员函数情况下

当子类中出现和父类同名的成员函数,子类的同名成员函数会隐藏掉父类中所有同名成员函数,如果想要通过子类对象访问到父类中被隐藏的同名成员函数,需要加父类作用域。 

#include<iostream>
// 父类
class Base{public:void func(){std::cout<<"Base-func调用~"<<std::endl;}  
};
// 子类
class Derived:public Base{public:void func(){std::cout<<"Derived-func调用~"<<std::endl;}  
};int main(){Derived d1; // 子类实例化d1.func(); // 访问自身   Derived-func调用~d1.Base::func(); // Base-func调用~return 0;
}

当子类中没有出现和父类同名的成员函数,可通过子类对象直接访问到父类中的成员函数。 

#include<iostream>
// 父类
class Base{public:void func(){std::cout<<"Base-func调用~"<<std::endl;}  
};
// 子类
class Derived:public Base{public:
};int main(){Derived d1; // 子类实例化d1.func(); // Base-func调用~return 0;
}

6.3 示例:静态成员变量情况下

6.3.1 通过对象访问 

当子类中出现和父类同名的静态成员变量,子类的同名静态成员变量会隐藏掉父类中所有同名静态成员变量,如果想要通过子类对象访问到父类中被隐藏的同名静态成员变量,需要加父类作用域。   

#include<iostream>
// 父类
class Base{public:static int a; // 静态成员变量类内声明
};
int Base::a=10; // 静态成员变量类外初始化// 子类
class Derived:public Base{public:static int a; // 静态成员变量类内声明 
};
int Derived::a=20; // 静态成员变量类外初始化int main(){Derived d1; // 子类实例化std::cout<<"Derived-a:"<<d1.a<<std::endl; // Derived-a:20std::cout<<"Base-a:"<<d1.Base::a<<std::endl; // Base-a:10return 0;
}

当子类中没有出现和父类同名的静态成员变量,可通过子类对象直接访问到父类中的静态成员变量。  

#include<iostream>
// 父类
class Base{public:static int a; // 静态成员变量类内声明
};
int Base::a=10; // 静态成员变量类外初始化// 子类
class Derived:public Base{
};int main(){Derived d1; // 子类实例化std::cout<<d1.a<<std::endl; // 10return 0;
}

6.3.2 通过类名来访问

#include<iostream>
// 父类
class Base{public:static int a; // 静态成员变量类内声明
};
int Base::a=10; // 静态成员变量类外初始化// 子类
class Derived:public Base{public:static int a; // 静态成员变量类内声明 
};
int Derived::a=20; // 静态成员变量类外初始化int main(){// 通过类名方式访问静态成员变量std::cout<<"Derived-a:"<<Derived::a<<std::endl; // Derived-a:20// 第一个::表示通过类名方式访问 第二个::表示访问父类作用域下std::cout<<"Base-a:"<<Derived::Base::a<<std::endl; // Base-a:10return 0;
}

6.4 示例:静态成员函数情况下

6.4.1 通过对象访问 

当子类中出现和父类同名的静态成员函数,子类的同名静态成员函数会隐藏掉父类中所有同名静态成员函数,如果想要通过子类对象访问到父类中被隐藏的同名静态成员函数,需要加父类作用域。  

#include<iostream>
// 父类
class Base{public:static void func(){std::cout<<"Base-func调用~"<<std::endl;}  
};
// 子类
class Derived:public Base{public:static void func(){std::cout<<"Derived-func调用~"<<std::endl;}  
};int main(){Derived d1; // 子类实例化d1.func(); // 访问自身   Derived-func调用~d1.Base::func(); // Base-func调用~return 0;
}

当子类中没有出现和父类同名的静态成员函数,可通过子类对象直接访问到父类中的静态成员函数。  

#include<iostream>
// 父类
class Base{public:static void func(){std::cout<<"Base-func调用~"<<std::endl;}  
};
// 子类
class Derived:public Base{
};int main(){Derived d1; // 子类实例化d1.func(); // Base-func调用~return 0;
}

6.4.2 通过类名来访问 

#include<iostream>
// 父类
class Base{public:static void func(){std::cout<<"Base-func调用~"<<std::endl;}  
};
// 子类
class Derived:public Base{public:static void func(){std::cout<<"Derived-func调用~"<<std::endl;}  
};int main(){// 通过类名访问静态成员函数Derived::func(); // Derived-func调用~Derived::Base::func(); // Base-func调用~return 0;
}

6.5 总结

无论是静态成员还是非静态成员(包括成员变量和成员函数):

  • 若子类中没有同名成员,则可通过子类实例直接访问父类成员
  • 若子类中有和父类相同的成员,则需要加父类作用域才能通过子类实例访问父类成员 

注意:静态成员属于类本身,不属于某个具体的对象,它们是共享的(相对于对象来说是共享的)。因此也可以通过类名直接访问它们。

七、多继承语法【可以认多个爹】

C++ 允许多继承(Multiple Inheritance),但它会带来一些复杂性,特别是命名冲突菱形继承(Diamond Problem),所以在实际开发中通常不推荐使用多继承,而是更倾向于组合(Composition)虚继承(Virtual Inheritance)来解决相关问题。

 7.1 多继承的基本语法

class A {
public:int valueA;
};class B {
public:int valueB;
};class C : public A, public B { // C 继承自 A 和 B
public:int valueC;
};

C 继承了 AB,因此 C 对象中同时包含 valueAvalueB。 

🚨 7.2. 多继承的命名冲突【作用域解析符 :: 解决命名冲突

当多个基类中存在同名成员,子类需要通过作用域解析符::)来区分,否则会产生二义性错误

⚠️ 命名冲突示例

#include <iostream>
using namespace std;class A {
public:int value = 10;
};class B {
public:int value = 20;
};class C : public A, public B { };int main() {C obj;// cout << obj.value; // ❌ 编译错误:value 有二义性cout << "A::value = " << obj.A::value << endl; // ✅ 访问 A 的 valuecout << "B::value = " << obj.B::value << endl; // ✅ 访问 B 的 valuereturn 0;
}

编译错误:

 🔹 解释

  • obj.value 直接访问会产生二义性错误,因为 AB 都有 value
  • 需要使用 obj.A::valueobj.B::value 明确指定要访问哪个基类的 value

💢 7.3. 菱形继承问题(Diamond Problem)【虚继承 virtual 解决菱形继承

        当一个类间接继承自同一个基类时,就可能导致菱形继承问题。即:两个派生类继承同一个基类,又有某个类同时继承着这两个派生类,这种继承被称为菱形继承,或者钻石继承。

7.3.1 菱形继承示例

class A {
public:int value = 10;
};class B : public A { }; // B 继承 A
class C : public A { }; // C 继承 A
class D : public B, public C { }; // D 继承 B 和 C

💥 菱形继承所带来的问题

  • D 继承了 BC,但 BC 都继承了 A,导致 D两份 A::value,这会造成数据冗余和二义性

7.3.2 解决方案:使用虚继承

#include<iostream>
class A { // 虚基类public:int value = 10;};class B : virtual public A { }; // 虚继承
class C : virtual public A { }; // 虚继承
class D : public B, public C { };int main() {D obj;std::cout << obj.value << std::endl; // ✅ 只有一份 A::valuereturn 0;
}

🔹 virtual 继承 确保 D 只有一份 A::value,避免数据冗余。 

7.3.3 虚继承解决菱形继承的底层原理 

虚继承解决菱形继承的底层原理请看这篇博文:C++中的菱形继承问题【使用虚继承方法来解决】-CSDN博客!!!!

八、Python中的 super() 等效于 Base::method() 调用

在 C++ 中,子类可以使用 Base::method() 调用父类的方法,类似于 Python 的 super()

#include<iostream>class Animal {public:void makeSound() {std::cout << "动物发出声音" << std::endl;}};class Dog : public Animal {
public:void makeSound() {Animal::makeSound();  // 调用父类方法std::cout << "汪汪!" << std::endl;}
};
int main(){Dog hashiqi; // 哈士奇hashiqi.makeSound();return 0;
}// 输出:
// 动物发出声音
// 汪汪!

C++ 继承机制强大,同时支持多重继承虚继承,如果有更复杂的需求,可以进一步探索 虚函数(virtual functions)抽象类(abstract classes)。🚀


http://www.mrgr.cn/news/94974.html

相关文章:

  • Python教学:lambda表达式的应用-由DeepSeek产生
  • Direct2D 极速教程(3) —— 画动态淳平
  • LeetCode[42] 接雨水
  • Opencv之计算机视觉一
  • 《深度学习》—— 模型部署
  • 导出的使用
  • PHP转GO Go语言环境搭建(Day1) 常见问题及解决方案指南
  • 8. Merge Sorted Array
  • 【数据结构】LinkedList与链表(1) + 经典面试OJ题解析 —— 有码有图有真相
  • Mysql:关于命名
  • 五、面向对象
  • 大模型知识蒸馏:技术演进与未来展望
  • Pydoll:告别WebDriver!Python异步Web自动化测试工具
  • Linux上的`i2c-tools`工具集的详细介绍;并利用它操作IMX6ULL的I2C控制器进而控制芯片AP3216C读取光照值和距离值
  • 使用Azure CDN进行子域名接管
  • 网络爬虫【爬虫库urllib】
  • 前端剪贴板操作:从传统方法到现代方案
  • 3D标定中的平面约束-平面方程的几何意义
  • OpenHarmony 开源鸿蒙北向开发——hdc工具安装
  • 自动驾驶背后的数学:特征提取中的线性变换与非线性激活