当前位置: 首页> 健康> 知识 > 遵义公共资源交易中心官网_优化网站排名公司_cfa一级看多久两分钟_黑龙江头条今日新闻

遵义公共资源交易中心官网_优化网站排名公司_cfa一级看多久两分钟_黑龙江头条今日新闻

时间:2025/7/9 22:01:52来源:https://blog.csdn.net/qq_45993770/article/details/143641363 浏览次数:0次
遵义公共资源交易中心官网_优化网站排名公司_cfa一级看多久两分钟_黑龙江头条今日新闻

在C++中,虚函数(Virtual Function)和纯虚函数(Pure Virtual Function)都是实现多态性的重要工具。虽然它们在概念上相关,但有着不同的用途和特性。以下将详细解释它们的区别、用途以及如何在实际编程中使用它们。


1. 基本定义

虚函数(Virtual Function)

虚函数是在基类中声明的,可以在派生类中被重写(覆盖)的函数。它允许通过基类指针或引用调用派生类中的函数实现,从而实现运行时多态。

class Base {
public:virtual void display() {std::cout << "Display from Base" << std::endl;}
};

纯虚函数(Pure Virtual Function)

纯虚函数是一个没有实现的虚函数,基类中声明为纯虚函数的类被称为抽象类。纯虚函数强制派生类必须提供该函数的具体实现,否则派生类也将成为抽象类,无法实例化。

class AbstractBase {
public:virtual void display() = 0; // 纯虚函数
};

2. 主要区别

特性虚函数(Virtual Function)纯虚函数(Pure Virtual Function)
定义方式virtual 返回类型 函数名(参数列表)virtual 返回类型 函数名(参数列表) = 0;
实现可以在基类中提供默认实现不提供实现,必须在派生类中实现
类类型基类可以是具体类(可实例化)基类必须是抽象类(不可实例化)
强制性派生类可以选择是否重写派生类必须重写,否则也是抽象类
用途提供默认行为,允许派生类覆盖定义接口,强制派生类实现特定行为

3. 详细说明

虚函数的特点

  1. 多态性

    • 虚函数允许在运行时决定调用哪个函数实现,这称为运行时多态
    • 通过基类指针或引用,可以调用派生类中重写的函数。
  2. 默认实现

    • 基类中可以为虚函数提供默认实现,派生类可以选择是否覆盖。
    • 如果派生类没有重写虚函数,调用基类的实现。
  3. 非抽象类

    • 包含虚函数的类仍然是具体类,可以被实例化。
  4. 语法

    class Base {
    public:virtual void display() {std::cout << "Display from Base" << std::endl;}
    };class Derived : public Base {
    public:void display() override { // 重写虚函数std::cout << "Display from Derived" << std::endl;}
    };
    

纯虚函数的特点

  1. 抽象性

    • 包含纯虚函数的类是抽象类,不能被实例化。
    • 纯虚函数没有实现,派生类必须提供具体实现。
  2. 接口定义

    • 纯虚函数用于定义接口,确保派生类实现特定的行为。
    • 类似于其他语言中的接口(如Java中的interface)。
  3. 强制重写

    • 派生类如果不实现所有继承的纯虚函数,仍然是抽象类,无法实例化。
  4. 语法

    class AbstractBase {
    public:virtual void display() = 0; // 纯虚函数virtual ~AbstractBase() = default; // 虚析构函数
    };class Derived : public AbstractBase {
    public:void display() override { // 必须实现纯虚函数std::cout << "Display from Derived" << std::endl;}
    };
    

4. 使用场景对比

虚函数的使用场景

  • 提供默认行为:基类提供一个通用的实现,派生类可以根据需要选择是否覆盖。
  • 可选覆盖:派生类可以继承基类的行为,或者根据需求提供特定实现。

示例

#include <iostream>
#include <vector>class Animal {
public:virtual void makeSound() {std::cout << "Some generic animal sound." << std::endl;}
};class Dog : public Animal {
public:void makeSound() override { // 重写虚函数std::cout << "Woof!" << std::endl;}
};class Cat : public Animal {// 不重写 makeSound,使用基类的默认实现
};int main() {std::vector<Animal*> animals = { new Dog(), new Cat() };for(auto animal : animals) {animal->makeSound();}// 输出:// Woof!// Some generic animal sound.// 清理内存for(auto animal : animals) {delete animal;}return 0;
}

纯虚函数的使用场景

  • 定义接口:创建一个接口,确保所有派生类实现特定的函数。
  • 强制实现:确保所有具体类实现某些关键功能,避免遗漏。

示例

#include <iostream>
#include <vector>// 抽象基类
class Shape {
public:virtual void draw() = 0; // 纯虚函数,强制派生类实现virtual ~Shape() = default;
};// 具体类
class Circle : public Shape {
public:void draw() override {std::cout << "Drawing a Circle." << std::endl;}
};class Rectangle : public Shape {
public:void draw() override {std::cout << "Drawing a Rectangle." << std::endl;}
};int main() {// Shape s; // 错误:无法实例化抽象类std::vector<Shape*> shapes = { new Circle(), new Rectangle() };for(auto shape : shapes) {shape->draw();}// 输出:// Drawing a Circle.// Drawing a Rectangle.// 清理内存for(auto shape : shapes) {delete shape;}return 0;
}

5. 示例对比

为了更直观地理解虚函数和纯虚函数的区别,以下通过两个完整的示例进行对比。

示例1:使用虚函数

#include <iostream>
#include <vector>class Printer {
public:virtual void print() {std::cout << "Printing from Printer" << std::endl;}
};class LaserPrinter : public Printer {
public:void print() override {std::cout << "Printing from LaserPrinter" << std::endl;}
};class InkjetPrinter : public Printer {
public:void print() override {std::cout << "Printing from InkjetPrinter" << std::endl;}
};int main() {std::vector<Printer*> printers = { new Printer(), new LaserPrinter(), new InkjetPrinter() };for(auto printer : printers) {printer->print();}// 输出:// Printing from Printer// Printing from LaserPrinter// Printing from InkjetPrinter// 清理内存for(auto printer : printers) {delete printer;}return 0;
}

说明

  • Printer 类提供了一个默认的 print 实现。
  • LaserPrinterInkjetPrinter 类重写了 print 函数。
  • 当调用 print 时,基类和派生类的实现都会被调用,具体取决于对象的实际类型。

示例2:使用纯虚函数

#include <iostream>
#include <vector>// 抽象基类
class Vehicle {
public:virtual void startEngine() = 0; // 纯虚函数virtual ~Vehicle() = default;
};// 具体类
class Car : public Vehicle {
public:void startEngine() override {std::cout << "Car engine started." << std::endl;}
};class Motorcycle : public Vehicle {
public:void startEngine() override {std::cout << "Motorcycle engine started." << std::endl;}
};int main() {// Vehicle v; // 错误:无法实例化抽象类std::vector<Vehicle*> vehicles = { new Car(), new Motorcycle() };for(auto vehicle : vehicles) {vehicle->startEngine();}// 输出:// Car engine started.// Motorcycle engine started.// 清理内存for(auto vehicle : vehicles) {delete vehicle;}return 0;
}

说明

  • Vehicle 类是一个抽象类,定义了一个纯虚函数 startEngine
  • CarMotorcycle 类必须实现 startEngine 函数。
  • 通过基类指针调用 startEngine,实现了多态性。

6. 关键点总结

特性虚函数(Virtual Function)纯虚函数(Pure Virtual Function)
定义virtual void func();virtual void func() = 0;
实现可以在基类中实现不在基类中实现,派生类必须实现
类类型基类可以实例化基类是抽象类,不能实例化
强制性派生类可以选择实现或使用基类实现派生类必须实现,或者继续保持抽象
典型用途提供可选的默认行为定义接口,强制派生类实现特定行为

关键点

  1. 虚函数提供灵活性

    • 允许基类提供默认实现,派生类可以根据需要选择覆盖或继承。
    • 适用于需要共享某些通用行为,但允许具体类进行定制的场景。
  2. 纯虚函数强制实现

    • 定义接口或抽象基类,确保所有具体类实现特定功能。
    • 适用于需要统一接口但行为由具体类定义的场景。
  3. 抽象类与具体类

    • 含有纯虚函数的类是抽象类,无法实例化,只能作为基类。
    • 含有虚函数但无纯虚函数的类是具体类,可以实例化。
  4. 多态性的实现

    • 虚函数和纯虚函数都是实现多态性的手段。
    • 通过基类指针或引用,可以调用具体类的实现,增强代码的灵活性和可扩展性。

7. 进一步阅读与学习

  • C++ 官方文档:深入了解虚函数和纯虚函数.
  • 设计模式:学习如何在设计模式中使用虚函数和纯虚函数,如模板方法模式和策略模式.
  • C++ 多态性:理解运行时多态的工作原理及其在面向对象编程中的应用。
关键字:遵义公共资源交易中心官网_优化网站排名公司_cfa一级看多久两分钟_黑龙江头条今日新闻

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com

责任编辑: