【C++】cpp虚函数和纯虚函数的声明和定义

文章目录

      • [一、虚函数(Virtual Function)](#一、虚函数(Virtual Function))
        • [1. 声明规则](#1. 声明规则)
        • [2. 示例代码](#2. 示例代码)
        • 输出结果
      • [二、纯虚函数(Pure Virtual Function)](#二、纯虚函数(Pure Virtual Function))
        • [1. 声明规则](#1. 声明规则)
        • [2. 示例代码](#2. 示例代码)
        • 输出结果
      • 三、关键区别总结
      • 四、注意事项

一、虚函数(Virtual Function)

虚函数是C++中实现运行时多态(动态绑定) 的核心机制,基类中声明为virtual的成员函数,派生类可重写(override)该函数,通过基类指针/引用调用时,会根据实际指向的对象类型调用对应版本。

1. 声明规则
  • 基类中使用virtual关键字声明,语法:virtual 返回值类型 函数名(参数列表);
  • 虚函数必须有定义(除非是纯虚函数),可在类内或类外定义。
  • 派生类重写虚函数时,virtual关键字可省略(编译器会自动识别),但建议显式写virtualoverride(C++11起)增强可读性。
2. 示例代码
cpp 复制代码
#include <iostream>
using namespace std;

// 基类
class Base {
public:
    // 声明虚函数(类内声明)
    virtual void show(); // 仅声明,类外定义

    // 类内定义的虚函数
    virtual void display() {
        cout << "Base::display()" << endl;
    }
};

// 虚函数的类外定义(必须加类名限定,virtual关键字仅在声明时用,定义时省略)
void Base::show() {
    cout << "Base::show()" << endl;
}

// 派生类
class Derived : public Base {
public:
    // 重写基类虚函数(virtual可省略,建议加override)
    void show() override { // override关键字:编译器检查是否真的重写了基类虚函数
        cout << "Derived::show()" << endl;
    }

    // 重写display,省略virtual(不推荐)
    void display() override {
        cout << "Derived::display()" << endl;
    }
};

int main() {
    Base* ptr = new Derived(); // 基类指针指向派生类对象
    ptr->show();    // 调用Derived::show()(动态绑定)
    ptr->display(); // 调用Derived::display()(动态绑定)
    delete ptr;
    return 0;
}
输出结果
复制代码
Derived::show()
Derived::display()

二、纯虚函数(Pure Virtual Function)

纯虚函数是没有实现 的虚函数,用于定义基类的接口,强制派生类重写该函数。包含纯虚函数的类称为抽象类,抽象类不能实例化(不能创建对象),仅能作为基类被继承。

1. 声明规则
  • 语法:virtual 返回值类型 函数名(参数列表) = 0;
  • 纯虚函数声明时必须加= 0 ,且类内仅声明,无定义(特殊情况:纯虚函数可在类外定义,但派生类仍需重写)。
  • 派生类必须重写所有纯虚函数,否则派生类也会成为抽象类,无法实例化。
2. 示例代码
cpp 复制代码
#include <iostream>
using namespace std;

// 抽象类(包含纯虚函数)
class Shape {
public:
    // 声明纯虚函数(无定义)
    virtual double getArea() = 0;

    // 纯虚函数也可以有默认实现(类外定义)
    virtual void printType() = 0;

    // 普通虚函数(有定义)
    virtual void show() {
        cout << "This is a shape." << endl;
    }
};

// 纯虚函数的类外定义(可选,派生类可通过Base::func()调用)
void Shape::printType() {
    cout << "Base Shape Type" << endl;
}

// 派生类:圆形
class Circle : public Shape {
private:
    double radius;
public:
    Circle(double r) : radius(r) {}

    // 必须重写纯虚函数getArea
    double getArea() override {
        return 3.14159 * radius * radius;
    }

    // 重写纯虚函数printType(可调用基类实现)
    void printType() override {
        Shape::printType(); // 调用基类的默认实现
        cout << "Circle Type" << endl;
    }
};

// 派生类:矩形
class Rectangle : public Shape {
private:
    double width, height;
public:
    Rectangle(double w, double h) : width(w), height(h) {}

    double getArea() override {
        return width * height;
    }

    void printType() override {
        cout << "Rectangle Type" << endl;
    }
};

int main() {
    // Shape s; // 错误:抽象类不能实例化
    Shape* shape1 = new Circle(5.0);
    Shape* shape2 = new Rectangle(4.0, 6.0);

    cout << "Circle Area: " << shape1->getArea() << endl;
    shape1->printType();
    shape1->show(); // 调用基类的虚函数

    cout << "\nRectangle Area: " << shape2->getArea() << endl;
    shape2->printType();

    delete shape1;
    delete shape2;
    return 0;
}
输出结果
复制代码
Circle Area: 78.53975
Base Shape Type
Circle Type
This is a shape.

Rectangle Area: 24
Rectangle Type

三、关键区别总结

特性 虚函数 纯虚函数
定义要求 必须有定义(类内/类外) 声明时= 0,类内无定义(可类外定义)
类的性质 基类可实例化 包含纯虚函数的类为抽象类,不可实例化
派生类要求 可重写,也可不重写 必须重写,否则派生类也是抽象类
用途 提供默认实现,支持多态 定义接口,强制派生类实现具体逻辑

四、注意事项

  1. 虚函数/纯虚函数不能是static(静态函数属于类,不属于对象,无法动态绑定)。
  2. 析构函数建议声明为虚函数(尤其是基类),避免派生类对象析构时内存泄漏。
  3. C++11起,重写虚函数时建议加override关键字,编译器会检查重写的正确性(参数、返回值匹配)。
  4. 纯虚函数的类外定义仅作为"默认实现",派生类重写后仍可通过基类::函数名()调用。
相关推荐
q_30238195561 小时前
Python实现基于多模态知识图谱的中医智能辅助诊疗系统:迈向智慧中医的新篇章
开发语言·python·知识图谱
橘颂TA1 小时前
【Linux】System V 通信——共享内存
linux·运维·服务器·c++
梨落秋霜1 小时前
Python入门篇【输入input】
开发语言·python
wen-pan1 小时前
Go 语言 GMP 调度模型深度解析
开发语言·go
Buxxxxxx2 小时前
DAY 34 模块和库的导入
开发语言·python
老前端的功夫2 小时前
前端水印技术深度解析:从基础实现到防破解方案
开发语言·前端·javascript·前端框架
oioihoii2 小时前
C++异常安全保证:从理论到实践
开发语言·c++·安全
霍格沃兹测试学院-小舟畅学2 小时前
性能测试入门:使用 Playwright 测量关键 Web 性能指标
开发语言·前端·php
动感小麦兜2 小时前
NAS学习
java·开发语言·eureka