C++ 中重要函数特性及相关机制的系统整理,涵盖面向对象、泛型编程、性能优化等核心场景:
一、面向对象核心机制(多态与继承)
1. 虚函数(Virtual Function)
定义:基类中用 virtual 声明的成员函数,允许派生类重写。
核心作用:实现运行时多态(动态绑定),通过基类指针 / 引用调用时,实际执行的是指向对象的类型对应的函数版本。
语法:virtual 返回类型 函数名(参数列表) { ... }
2. 函数重写(Override)
定义:派生类中定义与基类虚函数原型完全一致(返回值、函数名、参数列表相同)的函数,覆盖基类版本。
要求:
基类函数必须带 virtual。
C++11 可加 override 关键字强制检查重写合法性(避免拼写错误)。
示例:
cpp
运行
class Base { public: virtual void func() {} };
class Derived : public Base { public: void func() override {} }; // 重写
3. 纯虚函数与抽象类
纯虚函数:基类中声明但不实现的虚函数,格式 virtual 返回类型 函数名(参数) = 0;。
抽象类:含纯虚函数的类,无法实例化,仅作为基类使用;派生类必须重写所有纯虚函数才能实例化。
作用:定义接口规范(如 Shape 类的 area() 方法),强制派生类实现核心功能。
4. 虚析构函数
定义:基类析构函数声明为 virtual,确保通过基类指针删除派生类对象时,先调用派生类析构,再调用基类析构,避免内存泄漏。
示例:
cpp
运行
class Base { public: virtual ~Base() {} }; // 虚析构
5. 函数隐藏(Name Hiding)
场景:派生类中函数与基类函数同名但参数不同,基类函数被隐藏(即使基类函数是虚函数)。
注意:不同于重写(重写要求参数完全相同),易引发混淆,建议避免同名不同参设计。
二、函数重载与扩展
1. 函数重载(Overload)
定义:同一类中,函数名相同但参数列表不同(类型、个数、顺序),与返回值无关。
作用:简化相似功能的调用(如 add(int, int) 与 add(double, double)),编译器静态绑定。
2. 运算符重载(Operator Overloading)
定义:重定义运算符(如 +、<<、=)的行为,使自定义类型支持类似内置类型的操作。
形式:可作为成员函数(如 operator+)或友元函数(如 operator<<)。
示例:
cpp
运行
class Complex {
double real, imag;
public:
Complex operator+(const Complex& other) const { // 重载 +
return {real + other.real, imag + other.imag};
}
};
三、性能与资源管理
1. 移动构造函数与移动赋值运算符(C++11)
作用:“窃取” 临时对象(右值)的资源(如动态内存),避免拷贝开销,提升性能。
参数:右值引用 T&&,配合 std::move 使用。
示例:
cpp
运行
class MyString {
char* data;
public:
MyString(MyString&& other) noexcept : data(other.data) {
other.data = nullptr; // 原对象资源失效
}
};
2. const 成员函数
定义:函数声明后加 const,表示函数不修改对象成员(只读操作)。
作用:常量对象(const 类名 obj)只能调用 const 函数,保证代码安全性。
示例:int getValue() const { return value; }
四、泛型与匿名函数
1. 模板函数(Function Template)
定义:通用函数逻辑,支持多种数据类型,编译器自动生成具体类型的函数(泛型编程)。
作用:避免重复编写相似逻辑(如通用排序、比较)。
示例:
cpp
运行
template <typename T>
T max(T a, T b) { return a > b ? a : b; } // 支持 int、double 等
2. Lambda 表达式(匿名函数,C++11)
定义:临时匿名函数,可捕获上下文变量,简化回调、算法参数等场景。
格式:[捕获列表](参数) -> 返回类型 { 函数体 }
示例:
cpp
运行
#include <algorithm>
vector<int> v = {3,1,4};
sort(v.begin(), v.end(), [](int a, int b) { return a > b; }); // 降序排序
核心区别总结
特性 核心场景 / 作用 关键区分点
虚函数 + 重写 运行时多态,基类指针调用派生类函数 依赖 virtual 和函数原型一致
重载 同一类中同名函数的参数差异化 参数列表不同,静态绑定
纯虚函数 定义接口,抽象类无法实例化 强制派生类实现,格式带 = 0
移动函数 高效转移临时对象资源,避免拷贝 针对右值,用 && 参数
模板函数 泛型编程,支持多类型通用逻辑 编译器自动生成具体类型代码
Lambda 表达式 简化匿名回调,临时函数逻辑 捕获上下文变量,无需显式命名
这些特性是 C++ 灵活性和高效性的基础,掌握其适用场景和底层逻辑,是进阶高级编程的关键。
==============================================================================================
c++ 虚函数,和重构函数
在 C++ 中,虚函数(Virtual Function) 和重写(Override) 是面向对象编程中实现多态的核心机制。以下是详细解释:
1. 虚函数(Virtual Function)
定义:在基类中用 virtual 关键字声明的成员函数,允许派生类对其进行重写,从而实现 “运行时多态”。
作用:当通过基类指针或引用调用虚函数时,程序会根据指针 / 引用所指向的实际对象类型(而非指针 / 引用的声明类型)来调用对应的函数版本,这就是 “动态绑定”。
语法:在基类函数声明前加 virtual:
cpp
运行
class Base {
public:
virtual void func() { // 虚函数
cout << "Base::func()" << endl;
}
};
2. 重写(Override)
定义:派生类中定义一个与基类虚函数原型完全相同(返回值、函数名、参数列表均一致)的函数,称为 “重写”(也叫 “覆盖”)。
要求:
基类函数必须是虚函数(带 virtual)。
派生类函数与基类函数的返回值、函数名、参数列表必须完全一致(C++11 起允许协变返回类型,即返回派生类指针 / 引用)。
派生类函数的访问权限可以与基类不同(但通常建议保持一致)。
C++11 增强:可在派生类函数后加 override 关键字,强制编译器检查是否正确重写了基类虚函数,避免拼写错误等问题:
cpp
运行
class Derived : public Base {
public:
void func() override { // 重写基类虚函数,加 override 更安全
cout << "Derived::func()" << endl;
}
};
3. 示例:虚函数与重写的使用
cpp
运行
#include <iostream>
using namespace std;
class Base {
public:
virtual void show() { // 基类虚函数
cout << "Base show" << endl;
}
};
class Derived : public Base {
public:
void show() override { // 重写基类虚函数
cout << "Derived show" << endl;
}
};
int main() {
Base* ptr = new Derived(); // 基类指针指向派生类对象
ptr->show(); // 调用的是 Derived::show()(动态绑定)
delete ptr;
return 0;
}
输出:Derived show(若基类函数不加 virtual,则会调用 Base::show(),即静态绑定)
4. 注意事项
析构函数建议设为虚函数:当用基类指针删除派生类对象时,若析构函数不是虚函数,会导致派生类部分无法正确析构,造成内存泄漏。
cpp
运行
class Base {
public:
virtual ~Base() { ... } // 虚析构函数
};
静态函数、友元函数不能是虚函数:虚函数依赖于对象的动态类型,而静态函数属于类,友元函数不属于类成员。
重写与重载的区别:
重写:发生在基类与派生类之间,函数原型必须相同,依赖虚函数。
重载:发生在同一类中,函数名相同但参数列表不同,与虚函数无关。
通过虚函数和重写,C++ 实现了多态性,使得代码更灵活、可扩展,是面向对象设计的核心特性之一。
类似于这类高级运用函数,还有哪些
在 C++ 中,除了虚函数和重写(Override),还有许多支持面向对象高级特性或复杂逻辑实现的机制,以下是一些常用的 “高级函数” 或相关特性:
1. 纯虚函数与抽象类
纯虚函数:在基类中声明但不实现的虚函数,格式为 virtual 返回类型 函数名(参数) = 0;。
抽象类:包含纯虚函数的类,无法实例化,只能作为基类被继承。派生类必须重写所有纯虚函数才能被实例化。
作用:定义接口规范(类似 “契约”),强制派生类实现特定功能,是多态设计的重要基础。
cpp
运行
class Shape { // 抽象类
public:
virtual double area() const = 0; // 纯虚函数
};
class Circle : public Shape {
public:
double area() const override { return 3.14 * r * r; } // 必须实现
};
2. 虚析构函数
基类析构函数声明为 virtual,确保通过基类指针删除派生类对象时,会先调用派生类析构函数,再调用基类析构函数,避免内存泄漏。
cpp
运行
class Base {
public:
virtual ~Base() { cout << "Base 析构" << endl; } // 虚析构
};
class Derived : public Base {
public:
~Derived() override { cout << "Derived 析构" << endl; }
};
// 使用:
Base* ptr = new Derived();
delete ptr; // 正确调用 Derived 析构 → Base 析构
3. 函数重载(Overload)
同一类中,多个函数函数名相同但参数列表不同(参数类型、个数、顺序不同),与返回值无关。
作用:简化相似功能的函数调用,编译器通过参数自动匹配对应版本(静态绑定)。
cpp
运行
class Math {
public:
int add(int a, int b) { return a + b; }
double add(double a, double b) { return a + b; } // 重载
};
4. 函数隐藏(Name Hiding)
派生类中定义的函数与基类函数同名但参数不同,此时基类函数会被 “隐藏”(即使基类函数是虚函数),派生类对象 / 指针调用时只会匹配派生类的版本。
注意:隐藏不同于重写(重写要求参数完全相同),容易引发混淆,建议避免同名不同参的设计。
cpp
运行
class Base {
public:
virtual void func(int x) { cout << "Base: " << x << endl; }
};
class Derived : public Base {
public:
void func(double x) { cout << "Derived: " << x << endl; } // 隐藏基类 func(int)
};
// 调用:
Derived d;
d.func(10); // 调用 Derived::func(double)(10 被隐式转换为 double)
5. 移动构造函数与移动赋值运算符
C++11 引入,用于 “窃取” 临时对象(右值)的资源(如动态内存),避免不必要的拷贝,提升性能。
格式:参数为右值引用 T&&,通常配合 std::move 使用。
cpp
运行
class MyString {
private:
char* data;
public:
// 移动构造函数
MyString(MyString&& other) noexcept : data(other.data) {
other.data = nullptr; // 标记原对象资源已转移
}
// 移动赋值运算符
MyString& operator=(MyString&& other) noexcept {
if (this != &other) {
delete[] data;
data = other.data;
other.data = nullptr;
}
return *this;
}
};
6. 模板函数(Function Template)
定义通用函数逻辑,支持多种数据类型,编译器会根据传入参数自动生成具体类型的函数(泛型编程)。
作用:避免重复编写相似逻辑的函数(如通用排序、比较)。
cpp
运行
template <typename T>
T max(T a, T b) { // 模板函数
return a > b ? a : b;
}
// 使用:
max(3, 5); // 自动生成 int 版本
max(3.14, 2.7); // 自动生成 double 版本
7. Lambda 表达式(匿名函数)
临时定义的匿名函数,可捕获上下文变量,常用于简化回调函数、算法参数(如 std::sort)等场景。
格式:[捕获列表](参数) -> 返回类型 { 函数体 }
cpp
运行
#include <algorithm>
vector<int> v = {3, 1, 4};
// 用 Lambda 作为排序规则(降序)
sort(v.begin(), v.end(), [](int a, int b) { return a > b; });
8. 运算符重载(Operator Overloading)
重定义运算符(如 +、<<、= 等)的行为,使自定义类型支持类似内置类型的操作。
可以是成员函数或友元函数,需遵循运算符优先级和结合性。
cpp
运行
class Complex {
private:
double real, imag;
public:
Complex operator+(const Complex& other) const { // 重载 +
return {real + other.real, imag + other.imag};
}
};
9. const 成员函数
在函数声明后加 const,表示该函数不会修改对象的成员变量(只读操作)。
作用:保证常量对象(const 类名 对象)只能调用 const 函数,增强代码安全性。
cpp
运行
class MyClass {
public:
int getValue() const { // const 成员函数
return value; // 只能读,不能写
}
private:
int value;
};
这些特性共同支撑了 C++ 的灵活性和高效性,尤其是虚函数、模板、Lambda 等,在大型项目和高性能场景中应用广泛。理解它们的适用场景和底层原理,是掌握 C++ 高级编程的关键。Powered by ddoss.cn 12.0
©2015 - 2025 ddoss
渝公网安备50011302222260号
渝ICP备2024035333号
【实验平台安全承诺书】
小绿叶技术社区,优化网络中,点击查看配置信息
主机监控系统: 安全防火墙已开启检查cc攻击-下载文件完成后等待10s 恢复访问,检查连接数低于峰值恢复访问
您的IP:216.73.216.110,2025-12-01 13:42:12,Processed in 0.01837 second(s).