纯虚函数定义:

virtual void release(void* ptr) const = 0;
virtual void* allocate(size_t byte_size) const = 0;

对于上述代码第二行:返回值类型是 void*,不是 void

这里直接解引用是的非法的, 必须先转换类型:

void* p = alloc.allocate(16);
*p = 1;   // ❌ 编译错误

int* ip = static_cast<int*>(p);
*ip = 42;  //

= 0 的精确定义

纯虚函数(pure virtual function)表示:这个类本身不提供该函数的实现,任何可实例化的派生类都必须提供实现。

抽象类不能被实例化
DeviceAllocator a; // ❌ 编译错误
抽象类可以作为“接口类型”被指针 / 引用指向
std::unique_ptr<DeviceAllocator> p; // ✅

只要存在至少一个纯虚函数 (=0),这个类就是抽象类
派生类若不实现所有纯虚函数,也仍然是抽象类

纯虚函数是一种“强制接口契约(interface contract)”

虚函数有定义函数体和不定义两种,如果不定义的话,在派生类中有哪些方式去实现?

当一个**虚函数在基类中“没有函数体”**时,实际上只有两种情况:

情况 语法 是否必须在派生类实现
纯虚函数 virtual f() = 0; 必须
普通虚函数(声明但未定义) virtual f(); 必须(否则链接错误)

👉 不存在第三种


二、情况一:纯虚函数(= 0)——最常见、最规范

基类

struct Base {
  virtual void f() = 0;
};

含义:

Base 不提供实现
所有可实例化的派生类必须实现


派生类实现方式(唯一正确方式)

struct Derived : Base {
  void f() override {
    // 实现
  }
};

注意点:

否则不算实现。


三、情况二:虚函数声明但未定义(非常危险)

基类

struct Base {
  virtual void f();   // 注意:没有 =0
};

这是合法的吗?
👉 语法合法

但它意味着:

Base 声称“我有一个虚函数 f”,
但你在任何地方都找不到它的实现。


如果派生类实现了 —— 可以工作

struct Derived : Base {
  void f() override {
    // 实现
  }
};

✔ 编译
✔ 链接
✔ 运行


如果派生类没有实现 —— 链接期炸

struct Derived : Base {
};

错误不是编译错误,而是:

链接错误(undefined reference to Base::f)

因为:

👉 这是 C++ 新手非常容易踩的坑


四、纯虚函数“也可以有定义”?(高阶知识点)

这是很多人不知道的,但你现在的理解水平已经可以接受这个事实了

语法上是允许的:

struct Base {
  virtual void f() = 0;
};

void Base::f() {
  // 基类实现
}

这是什么意思?

  • Base 仍然是抽象类(因为 =0
  • 派生类 仍然必须实现
  • 但派生类可以显式调用基类版本

派生类调用基类纯虚实现

struct Derived : Base {
  void f() override {
    Base::f();  // 合法!
    // 扩展逻辑
  }
};

👉 这种模式用于:


五、派生类实现虚函数的“全部方式”总结

✅ 标准 override(最常见)

void f() override { ... }

✅ 不写 override(合法但不推荐)

void f() { ... }

❌ 签名不一致(不会覆盖)

void f() const;   // ❌ 如果基类没有 const

结果:


✅ 使用 final(禁止再被重写)

void f() override final { ... }