C++ 面向对象

C++ 面向对象

C++作为面向对象编程(OOP)的经典语言,其核心优势在于通过封装、继承、多态三大特性实现代码的复用、扩展与维护。本文 主要介绍C++面向对象核心知识点,搭配代码示例和表格总结。

一、面向对象三大核心特性

面向对象编程的本质是"将数据与操作数据的方法绑定",通过三大特性解决代码冗余、扩展性差等问题。

1.1 封装(Encapsulation):数据安全

定义

将类的数据(成员变量)操作数据的方法(成员函数) 打包在一起,通过访问修饰符限制外部对内部数据的直接访问,仅暴露指定接口供外部调用。

核心目的
  • 隐藏实现细节,提高代码安全性(避免外部误修改内部数据);
  • 降低代码耦合度,外部仅需关注接口功能,无需关心内部实现。
访问修饰符

C++提供3种访问修饰符,控制成员的可见性,具体规则如下:

访问修饰符 类内部访问 子类(派生类)访问 外部(类实例/其他类)访问 典型用途
public 暴露接口(成员函数/常用变量)
private 隐藏核心数据(如动态分配的内存)
protected 子类需要继承的中间数据/方法
代码示例
cpp 复制代码
#include <iostream>
#include <string>
using namespace std;

class Person {
private:
    // 私有成员:外部无法直接访问,仅类内可操作
    string name;
    int age;

public:
    // 公有接口:外部通过接口操作私有数据
    Person(string n, int a) : name(n), age(a) {} // 构造函数初始化

    // 读取私有数据
    string getName() const { return name; }
    int getAge() const { return age; }

    // 修改私有数据(可添加逻辑校验)
    void setAge(int a) {
        if (a >= 0 && a <= 120) { // 避免设置不合理年龄
            age = a;
        } else {
            cout << "年龄输入非法!" << endl;
        }
    }
};

int main() {
    Person p("张三", 20);
    cout << "姓名:" << p.getName() << endl; // 输出:张三
    cout << "初始年龄:" << p.getAge() << endl; // 输出:20

    p.setAge(25); // 合法修改
    cout << "修改后年龄:" << p.getAge() << endl; // 输出:25

    p.setAge(150); // 非法修改,触发提示
    return 0;
}

1.2 继承(Inheritance):代码复用

定义

让一个类(子类/派生类 )继承另一个类(父类/基类 )的属性和方法,并可在父类基础上扩展新功能,实现代码复用。

继承的类型
继承类型 核心目的 实现方式
实现继承 复用父类的代码与实现 子类继承父类的非虚成员函数与数据
接口继承 构建多态基础,统一接口规范 子类继承父类的纯虚函数(抽象类)
核心规则
  • 子类默认继承父类的所有成员(public/protected/private),但访问权限受继承方式影响(如private继承会将父类public成员变为子类private);
  • 子类构造时会先调用父类构造函数,析构时先调用子类析构函数;
  • 支持多层继承(如A→B→C)和多重继承(如C→AC→B)。
代码示例
cpp 复制代码
#include <iostream>
#include <string>
using namespace std;

// 父类(基类)
class Animal {
protected:
    string name; // 受保护成员:子类可访问,外部不可访问
public:
    // 父类构造函数
    Animal(string n) : name(n) {}

    // 父类普通方法
    void eat() {
        cout << name << " 在吃东西" << endl;
    }
};

// 子类(派生类):公有继承Animal
class Dog : public Animal {
public:
    // 子类构造函数:必须先初始化父类
    Dog(string n) : Animal(n) {}

    // 子类扩展新方法
    void bark() {
        cout << name << " 汪汪叫!" << endl;
    }
};

int main() {
    Dog dog("旺财");
    dog.eat();  // 继承父类方法:输出"旺财 在吃东西"
    dog.bark(); // 子类扩展方法:输出"旺财 汪汪叫!"
    return 0;
}

1.3 多态(Polymorphism):灵活扩展

定义

"同一接口,不同实现"------通过父类指针/引用指向子类对象,调用相同函数时,根据对象的实际类型执行不同逻辑,大幅提升代码扩展性。

多态的分类
多态类型 别称 绑定时机 实现方式 适用场景
编译时多态 静态多态 编译期 函数重载、运算符重载 参数类型/数量已知的场景
运行时多态 动态多态 运行期 虚函数(virtual)+ 重写 统一接口处理不同对象的场景
运行时多态的核心条件
  1. 父类声明虚函数(virtual关键字);
  2. 子类重写(override)父类虚函数(函数名、参数、返回值完全一致);
  3. 通过父类指针或引用调用虚函数。
代码示例(运行时多态)
cpp 复制代码
#include <iostream>
#include <string>
using namespace std;

// 父类:含虚函数
class Animal {
protected:
    string name;
public:
    Animal(string n) : name(n) {}

    // 虚函数:允许子类重写
    virtual void speak() {
        cout << name << " 发出声音" << endl;
    }
};

// 子类Dog:重写虚函数
class Dog : public Animal {
public:
    Dog(string n) : Animal(n) {}
    void speak() override { // override关键字:确保重写正确(C++11+)
        cout << name << " 汪汪汪!" << endl;
    }
};

// 子类Cat:重写虚函数
class Cat : public Animal {
public:
    Cat(string n) : Animal(n) {}
    void speak() override {
        cout << name << " 喵喵喵!" << endl;
    }
};

// 统一接口:接收父类指针
void animalSpeak(Animal* animal) {
    animal->speak(); // 运行时根据实际对象类型调用对应方法
}

int main() {
    Dog dog("旺财");
    Cat cat("咪宝");

    animalSpeak(&dog); // 输出:旺财 汪汪汪!
    animalSpeak(&cat); // 输出:咪宝 喵喵喵!
    return 0;
}
三大特性对比总结
特性 核心思想 核心作用 关键关键字/技术
封装 数据+方法打包,隐藏细节 提高安全性、降低耦合度 public/private/protected
继承 子类复用父类功能 减少代码冗余、支持扩展 public/private/protected(继承方式)
多态 同一接口,不同实现 提升代码扩展性、灵活性 virtual/override、虚函数表

二、核心概念辨析(易混淆点)

2.1 重载(Overload)vs 重写(Override)

重载 : 函数名相同,参数不同,发生在同一个作用域(类内)。

重写:派生类中重写父类的虚函数,函数名、参数、返回值完全相同,使用virtual 和 overide 关键字

对比表如下:

对比维度 重载(Overload) 重写(Override)
作用域 同一类内部 父类与子类之间(继承关系)
函数签名 函数名相同,参数(类型/数量/顺序)不同 函数名、参数、返回值完全相同
返回值影响 与返回值无关(不能靠返回值区分) 必须与父类一致(协变除外)
关键字要求 父类需virtual,子类可加override
绑定时机 编译期(静态绑定) 运行期(动态绑定)
多态类型 编译时多态 运行时多态
重载代码示例
cpp 复制代码
//重载
class A { 
public: 
	void show(int x) {} 
	void show(double x) {} 
};
重写代码示例
cpp 复制代码
//重写
class A { 
public: 
	virtual void speak() {} 
}; 

class B : public A { 
public: 
	void speak() override {} 
}; 

2.2 深拷贝(Deep Copy)vs 浅拷贝(Shallow Copy)

当类包含动态分配资源 (如堆内存指针)时,拷贝对象需区分深拷贝与浅拷贝,否则会导致内存泄漏或重复释放。

深拷贝是对对象的完全独立复制,包括对象内部动态分配的资源。在深拷贝中,不仅复制对象的值,还会复制对象所指向的堆上的数据。

对比表如下:

对比维度 浅拷贝(Shallow Copy) 深拷贝(Deep Copy)
拷贝内容 仅复制成员变量的值(指针复制地址) 复制成员变量+动态分配的资源(指针指向新内存)
资源归属 原对象与新对象共享动态资源 原对象与新对象各自拥有独立资源
实现方式 编译器默认生成(拷贝构造函数/赋值运算符) 手动实现拷贝构造函数和赋值运算符
风险 重复释放内存、内存泄漏 无(需手动管理内存)
浅拷贝代码示例
cpp 复制代码
class Shallow { 
public: 
	int* data; 
	Shallow(int x) { 
		data = new int(x); 
	} 
	// 默认浅拷贝 
}; 
深拷贝代码示例
cpp 复制代码
class Deep { 
public: 
	int* data; 
	Deep(int x) { 
		data = new int(x); 
	} 
	// 手动深拷贝 
	Deep(const Deep& other) { 
		data = new int(*other.data); 
	} 
	// 赋值运算符重载 
	Deep& operator=(const Deep& other) { 
		if (this != &other) { 
			delete data; 
			data = new int(*other.data); 
		} 
		return *this; 
	} 
	~Deep() { 
		delete data; 
	} 
}; 

三、构造函数与析构函数:生命周期管理

构造函数负责对象的初始化,析构函数负责对象的资源清理,二者是面向对象中管理对象生命周期的核心。

3.1 构造函数(Constructor)

定义

对象创建时自动调用的特殊成员函数,用于初始化成员变量、分配资源(如堆内存、文件句柄)。

核心特点
  • 函数名与类名完全一致,无返回类型(包括void);
  • 可重载(支持多个构造函数,参数不同);
  • 若未手动定义,编译器会生成默认构造函数(无参数、无实现);
  • 构造顺序:先父类构造,再子类构造。
构造函数的类型
类型 定义与作用
默认构造函数 无参数,用于无初始化值的对象创建
带参数构造函数 含参数,支持自定义初始化
拷贝构造函数 接收同类型对象引用,创建副本
委托构造函数 一个构造函数调用同类另一个构造函数,减少冗余
默认构造函数代码示例
cpp 复制代码
class A { 
public: 
	A() { 
		cout << "默认构造" << endl; 
	} 
}; 
A a; // 调用默认构造 
带参数构造函数代码示例
cpp 复制代码
class A { 
public: 
	int x; 
	A(int val) : x(val) {} // 初始化列表 
}; 
A a(10); // x=10 
拷贝构造函数代码示例
cpp 复制代码
class A { 
public: 
	int x; 
	A(const A& other) : x(other.x) {} 
}; 
A a1(10); 
A a2 = a1; // 拷贝构造,a2.x=10 
委托构造函数代码示例
cpp 复制代码
class A { 
public: 
	int x; 
	A(int val) : x(val) {} 
	A() : A(0) {} // 委托给带参数构造,x默认0 
}; 
A a; // x=0 

3.2 析构函数(Destructor)

定义

对象生命周期结束时(如出作用域、delete调用)自动调用的特殊成员函数,用于释放资源(如堆内存、关闭文件)。

核心特点
  • 函数名:~类名,无参数、无返回类型,不能重载(一个类仅一个析构函数);
  • 若未手动定义,编译器生成默认析构函数(仅释放栈内存,不处理堆资源);
  • 析构顺序:先子类析构,再父类析构。
虚析构函数
作用

当通过父类指针删除子类对象时,确保子类析构函数被调用,避免子类资源泄漏。

代码示例(虚析构函数的必要性)
cpp 复制代码
#include <iostream>
using namespace std;

class Base {
public:
    Base() { cout << "Base构造" << endl; }
    // 非虚析构函数(错误示范)
    ~Base() { cout << "Base析构" << endl; }
};

class Derived : public Base {
private:
    int* data;
public:
    Derived() : data(new int(10)) { cout << "Derived构造" << endl; }
    ~Derived() {
        delete data; // 释放子类动态资源
        cout << "Derived析构" << endl;
    }
};

int main() {
    Base* ptr = new Derived(); // 父类指针指向子类对象
    delete ptr; // 仅调用Base析构,Derived析构未调用→内存泄漏
    return 0;
}
修正:将父类析构改为虚析构
cpp 复制代码
class Base {
public:
    Base() { cout << "Base构造" << endl; }
    virtual ~Base() { cout << "Base析构" << endl; } // 虚析构函数
};

// 输出结果(正确):
// Base构造
// Derived构造
// Derived析构
// Base析构

3.3 关键问题:为什么构造函数不能是虚函数?

  1. vptr初始化时机矛盾 :虚函数依赖虚指针(vptr)指向虚函数表(vtable),但vptr在构造函数执行前由编译器初始化,且先指向父类vtable;若构造函数是虚函数,调用时vptr未指向子类vtable,动态绑定无法生效。

  2. 构造逻辑冲突:构造函数的核心是"创建对象",需明确初始化顺序(父类→子类);而虚函数的核心是"动态绑定",依赖对象已完全创建,二者逻辑矛盾。

一是构造函数执行时,虚指针(vptr)还未指向子类的虚函数表,动态绑定无法生效,虚函数失去意义;二是父类构造阶段子类成员未初始化,若强行通过虚构造调用子类逻辑,会访问未初始化的资源,引发程序崩溃。因此 C++ 直接禁止构造函数声明为虚函数。

四、虚函数与虚函数表:多态的底层实现

运行时多态的核心是虚函数表(vtable)虚指针(vptr),理解其底层机制是掌握C++多态的关键。

4.1 核心概念

概念 定义与作用 级别(类/对象)
虚函数表(vtable) 编译期为含虚函数的类生成的"函数地址数组",存储该类所有虚函数的地址 类级别(所有对象共享)
虚指针(vptr) 每个对象隐含的隐藏指针,指向所属类的vtable 对象级别(每个对象独有)

4.2 底层工作流程(以Animal→Dog为例)

  1. 编译期 :编译器为Animal(含虚函数)和Dog(重写虚函数)分别生成vtable:
    • Animal的vtable:存储Animal::speak()的地址;
    • Dog的vtable:基于Animal的vtable构建,覆盖speak()Dog::speak()的地址。
  2. 运行期构造阶段
    • 创建Dog对象时,先调用Animal构造函数,vptr指向Animal的vtable;
    • Animal构造完成后,调用Dog构造函数,vptr更新为指向Dog的vtable。
  3. 调用虚函数时
    • 通过父类指针Animal* ptr = new Dog()调用ptr->speak()
    • 编译器通过ptr指向的对象的vptr找到Dog的vtable;
    • 从vtable中取出Dog::speak()的地址,执行对应逻辑。

4.3 虚函数表常见问题

问题 答案
虚表会拖慢程序吗? 影响极小。虚函数调用是"vptr→vtable→函数地址"的定向跳转,时间复杂度O(1),仅比普通函数调用慢微乎其微
虚表是编译期还是运行期生成? 编译期生成。每个含虚函数的类在编译时生成唯一vtable,运行时仅通过vptr指向即可
无虚函数的类有vtable吗? 无。仅当类含虚函数(或继承自含虚函数的类)时,编译器才生成vtable和vptr
虚表是对象级别的吗? 不是,是类级别。同一类的所有对象共享一张vtable,仅需各自存储vptr即可(节省内存)
非虚函数会进入vtable吗? 不会。仅虚函数会被存入vtable,非虚函数调用是静态绑定,与vtable无关
构造函数/静态成员函数能是虚函数吗? 不能。构造函数因vptr初始化时机矛盾;静态成员函数无this指针,无法指向vtable

五、抽象类与纯虚函数:接口规范

5.1 纯虚函数(Pure Virtual Function)

定义

没有实现的虚函数,声明格式为virtual 返回值 函数名(参数) = 0;,强制子类提供实现。

核心特点
  • 无函数体(仅声明);
  • 包含纯虚函数的类无法实例化;
  • 子类必须重写纯虚函数,否则子类也无法实例化(成为抽象类)。

5.2 抽象类(Abstract Class)

定义

包含至少一个纯虚函数的类,本质是"接口规范",用于定义子类必须实现的功能,不能直接创建对象。

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

// 抽象类:含纯虚函数
class Shape {
public:
    // 纯虚函数:定义接口,无实现
    virtual void draw() const = 0;
    virtual double area() const = 0;
};

// 子类Circle:实现纯虚函数
class Circle : public Shape {
private:
    double radius;
public:
    Circle(double r) : radius(r) {}

    void draw() const override {
        cout << "绘制圆形" << endl;
    }

    double area() const override {
        return 3.14 * radius * radius;
    }
};

int main() {
    // Shape s; // 错误:抽象类不能实例化
    Shape* circle = new Circle(5);
    circle->draw(); // 输出:绘制圆形
    cout << "面积:" << circle->area() << endl; // 输出:78.5
    delete circle;
    return 0;
}

5.3 虚函数vs纯虚函数对比表

对比维度 虚函数(Virtual Function) 纯虚函数(Pure Virtual Function)
实现情况 有默认实现(基类中提供) 无实现(仅声明)
子类要求 可选重写(不重写则使用基类实现) 必须重写(否则子类为抽象类)
类的实例化 所在类可实例化 所在类为抽象类,不可实例化
核心作用 实现运行时多态 定义接口规范,强制子类实现功能
声明格式 virtual void func() {} virtual void func() = 0;

六、运算符重载:让自定义类型支持运算符

6.1 定义与本质

运算符重载是"将运算符重新定义为成员函数或非成员函数",本质是函数调用,让自定义类型(如PersonCircle)支持+==<<等运算符。

核心规则
  • 不能改变运算符的优先级、结合性、操作数个数;
  • 不能发明新运算符(如@#);
  • 部分运算符必须作为成员函数(如=[]->());
  • 运算符函数名格式:operator++为要重载的运算符)。

6.2 常见运算符重载

运算符类型 建议实现方式
算术运算符(+、-) 非成员函数(友元)
赋值运算符(=) 成员函数
输出运算符(<<) 非成员函数(友元)
下标运算符([]) 成员函数
算术运算符(+)重载代码示例(以Point类为例)
cpp 复制代码
class Point { 
public: 
	int x, y; 
	Point(int x=0, int y=0) : x(x), y(y) {} 
	// 友元函数重载+ 
	friend Point operator+(const Point& p1, const Point& p2) { 
		return Point(p1.x+p2.x, p1.y+p2.y); 
	} 
}; 
Point p1(1,2), p2(3,4); 
Point p3 = p1 + p2; // (4,6) 
赋值运算符(=)重载代码示例
cpp 复制代码
Point& operator=(const Point& other) { 
	if (this != &other) { 
		x = other.x; 
		y = other.y; 
	} 
	return *this; 
} 
输出运算符(<<)重载代码示例
cpp 复制代码
friend ostream& operator<<(ostream& os, const Point& p) { 
	os << "(" << p.x << "," << p.y << ")"; 
	return os; 
} 
cout << p1; // 输出(1,2) 
下标运算符([])重载代码示例
cpp 复制代码
int& operator[](int idx) { 
	if (idx == 0) return x; 
	else if (idx == 1) return y; 
	throw "下标越界"; 
} 
Point p(1,2); 
cout << p[0]; // 输出1 

6.3 不建议重载的运算符

  • 逗号运算符(,):本身定义了求值顺序,重载后易混淆;
  • 逻辑与(&&)、逻辑或(||):重载后失去短路求值特性;
  • 取地址运算符(&):默认行为已满足大多数场景,重载易出错。

七、静态成员:类级别的共享资源

静态成员(静态成员变量、静态成员函数)属于类本身,而非对象,所有对象共享同一资源,常用于实现全局计数器、工具函数等。

7.1 静态成员变量(Static Member Variable)

核心特点
  • 存储在全局数据区,而非对象内存中;
  • 必须在类外定义并初始化(类内仅声明);
  • 可通过类名::变量名对象.变量名访问(推荐类名访问)。
代码示例
cpp 复制代码
#include <iostream>
using namespace std;

class Student {
public:
    static int count; // 类内声明静态成员变量(计数器)
    string name;

    Student(string n) : name(n) {
        count++; // 每创建一个对象,计数器+1
    }
};

// 类外定义并初始化静态成员变量
int Student::count = 0;

int main() {
    Student s1("张三");
    Student s2("李四");

    cout << "学生总数:" << Student::count << endl; // 输出2(推荐)
    cout << "学生总数:" << s1.count << endl; // 输出2(不推荐)
    return 0;
}

7.2 静态成员函数(Static Member Function)

核心特点
  • 无隐含this指针(无法访问非静态成员变量/函数);
  • 可通过类名::函数名直接调用,无需创建对象;
  • 不能是虚函数(无this指针,无法指向vtable)。
代码示例
cpp 复制代码
class MathTool {
public:
    // 静态成员函数:工具函数(无需对象)
    static int max(int a, int b) {
        return a > b ? a : b;
    }
};

int main() {
    // 直接通过类名调用,无需创建MathTool对象
    cout << MathTool::max(10, 20) << endl; // 输出20
    return 0;
}

7.3 静态成员vs普通成员对比表

对比维度 静态成员(变量/函数) 普通成员(变量/函数)
归属 类级别(所有对象共享) 对象级别(每个对象独有)
访问方式 类名::成员名(推荐)、对象.成员名 对象.成员名、指针->成员名
this指针 有(隐含参数)
访问限制 只能访问静态成员 可访问静态+非静态成员
内存分配 全局数据区(程序启动时分配) 对象内存中(创建对象时分配)
虚函数支持 不支持(静态函数不能是虚函数) 支持(普通成员函数可声明为虚函数)

八、多重继承与菱形问题

8.1 多重继承(Multiple Inheritance)

定义

一个子类同时继承多个父类(如class C : public A, public B),可复用多个父类的功能,但易引发二义性。

代码示例(未解决菱形问题)
cpp 复制代码
#include <iostream>
using namespace std;

// 顶层父类
class Animal {
public:
    void eat() {
        cout << "Animal 吃东西" << endl;
    }
};

// 中间父类1
class Mammal : public Animal {};

// 中间父类2
class Bird : public Animal {};

// 子类:同时继承Mammal和Bird(菱形继承)
class Bat : public Mammal, public Bird {};

int main() {
    Bat bat;
    // bat.eat(); // 错误:二义性(Mammal::eat和Bird::eat都继承自Animal)
    return 0;
}

8.2 菱形问题(Diamond Problem)

现象

当子类间接继承自同一个顶层父类(如Bat→Mammal→AnimalBat→Bird→Animal)时,子类会包含顶层父类的两个副本,导致调用父类成员时出现二义性。

解决方案:虚继承(Virtual Inheritance)

在中间父类继承顶层父类时,添加virtual关键字,确保子类仅包含顶层父类的一个副本,消除二义性。

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

class Animal {
public:
    void eat() {
        cout << "Animal 吃东西" << endl;
    }
};

// 虚继承:Mammal共享Animal副本
class Mammal : virtual public Animal {};

// 虚继承:Bird共享Animal副本
class Bird : virtual public Animal {};

class Bat : public Mammal, public Bird {};

int main() {
    Bat bat;
    bat.eat(); // 正确:仅一个Animal副本,输出"Animal 吃东西"
    return 0;
}

九、常见面试题

面试问题 核心答案
C++面向对象三大特性是什么?分别作用? 封装(数据安全)、继承(代码复用)、多态(灵活扩展)
重载和重写的区别? 重载:同作用域、参数不同、编译期绑定;重写:继承关系、签名相同、运行期绑定
构造函数为什么不能是虚函数? vptr未初始化,动态绑定无法生效;构造逻辑需明确顺序,与虚函数矛盾
析构函数为什么要声明为虚函数? 避免父类指针删除子类对象时,子类析构函数未调用导致资源泄漏
虚函数表是类级别还是对象级别? 类级别(所有对象共享),vptr是对象级别
深拷贝和浅拷贝的区别? 浅拷贝共享动态资源(风险),深拷贝复制动态资源(安全)
抽象类的特点? 含纯虚函数,不能实例化,子类必须重写纯虚函数
哪些函数不能声明为虚函数? 构造函数、静态成员函数、内联函数、友元函数、普通非成员函数
多重继承的问题及解决方案? 菱形继承导致二义性;解决方案:虚继承(virtual关键字)

十、总结

  1. C++面向对象核心是封装、继承、多态,其中多态依赖虚函数表(vtable)和虚指针(vptr)实现运行时动态绑定;
  2. 易混淆概念中,重载是同作用域参数不同的静态绑定,重写是继承关系下的动态绑定,深拷贝需手动实现以避免动态资源共享风险;
  3. 关键细节上,构造函数不能为虚函数,析构函数建议设为虚函数,抽象类含纯虚函数不可实例化,多重继承需用虚继承解决菱形问题。.

C++多态的本质是"接口统一,实现各异 ",其底层依赖vtablevptr的协作,核心流程可总结为:

  1. 编译期:为含虚函数的类生成vtable(存储虚函数地址);
  2. 运行期构造:对象的vptr在父类构造时指向父类vtable,子类构造时更新为子类vtable;
  3. 调用虚函数:通过父类指针/引用找到对象的vptr,再通过vtable定位到实际要执行的函数地址,实现动态绑定。
相关推荐
重生之后端学习1 小时前
62. 不同路径
开发语言·数据结构·算法·leetcode·职场和发展·深度优先
栗子~~1 小时前
hardhat 单元测试时如何观察gas消耗情况
开发语言·单元测试·区块链·智能合约
The hopes of the whole village1 小时前
Matlab FFT分析
开发语言·matlab
兰文彬1 小时前
n8n 2.x版本没有内嵌Python环境
开发语言·python
yiyaozjk1 小时前
Go基础之环境搭建
开发语言·后端·golang
谁动了我的代码?1 小时前
VNC中使用QT的GDB调试,触发断点时与界面窗口交互导致整个VNC冻结
开发语言·qt·svn
We་ct2 小时前
LeetCode 212. 单词搜索 II:Trie+DFS 高效解法
开发语言·算法·leetcode·typescript·深度优先·图搜索算法·图搜索
样例过了就是过了2 小时前
LeetCode热题100 路径总和 III
数据结构·c++·算法·leetcode·链表
OxyTheCrack2 小时前
【C++】简述main函数中的argc与argv
开发语言·c++
历程里程碑2 小时前
Linux 49 HTTP请求与响应实战解析 带http模拟实现源码--万字长文解析
java·开发语言·网络·c++·网络协议·http·排序算法