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定位到实际要执行的函数地址,实现动态绑定。
相关推荐
weixin_445402302 小时前
C++中的命令模式变体
开发语言·c++·算法
Hgfdsaqwr2 小时前
实时控制系统优化
开发语言·c++·算法
CSDN_RTKLIB2 小时前
Visual Studio不改变文件编码情况下解决C2001
c++·ide·visual studio
D_evil__2 小时前
【Effective Modern C++】第三章 转向现代C++:15. 尽可能使用constexpr
c++
2301_821369613 小时前
嵌入式实时C++编程
开发语言·c++·算法
sjjhd6523 小时前
多核并行计算优化
开发语言·c++·算法
一起养小猫3 小时前
Flutter for OpenHarmony 实战 表单处理与验证完整指南
android·开发语言·前端·javascript·flutter·harmonyos
leiming63 小时前
FreeRTOS 的任务与 Linux
java·开发语言
田野追逐星光3 小时前
STL的容器vector的模拟实现
开发语言·c++