跳转到主内容
极星编程网:以代码为星,赴技术山海!

c++中纯虚函数怎么定义_c++抽象类接口设计【进阶】

纯虚函数必须在声明末尾写=0且无函数体,含纯虚函数的类为抽象类不可实例化,但可定义指针或引用实现多态;派生类未重写所有纯虚函数仍为抽象类;纯虚函数可有默认实现,但调用需显式作用域限定。 纯虚函数的定义语法必须带 = 0 在 C++ 类中声明纯虚函数,核心是函数声明末尾加上
= 0
,且该函数不能有函数体(哪怕写成
{}
也会编译失败)。它只出现在类定义内部,用于表明该函数必须由派生类实现。 常见错误包括: 漏掉
= 0
,结果变成普通虚函数,基类可实例化,失去抽象约束 在类内写了函数体,如
virtual void foo() = 0 { }
,编译器直接报错 把
= 0
写在函数声明之外,比如放在注释后或换行后,会被视为语法错误 正确写法示例:
class Shape { public: virtual double area() const = 0; // ✅ 纯虚函数 virtual ~Shape() = default; };
含纯虚函数的类自动成为抽象类 只要一个类中至少有一个纯虚函数,该类就不可实例化——即使其他所有函数都已实现。这不是靠关键字
abstract
控制(C++ 没这关键字),而是语言规则强制的。 使用场景上要注意: 立即学习 “ C++免费学习笔记(深入) ”; C函数速查手册(CHM版) C函数速查手册(CHM版) 下载 不能对抽象类调用
new Shape
或声明
Shape s;
,否则编译失败,错误信息类似:
error: cannot declare variable 's' to be of abstract type 'Shape'
可以定义指向抽象类的指针或引用,这是多态调用的基础,例如
Shape* p = new Circle;
派生类若未重写全部纯虚函数,它本身仍是抽象类,也无法实例化 纯虚函数可以有默认实现,但调用需显式限定 纯虚函数允许在类外提供定义(即函数体),但这不改变其“纯虚”性质,也不影响抽象类判定。这种写法常用于提供通用逻辑,同时强制接口契约。 关键点在于:派生类中若要调用该默认实现,必须显式通过 作用域 解析符调用,例如
Base::func()
;否则仅靠
func()
会触发纯虚调用崩溃(运行时 undefined behavior)。 示例:
class Base { public: virtual void log() const = 0; }; void Base::log() const { std::cout << "default log\n"; } // ✅ 合法定义

class Derived : public Base { public: void log() const override { Base::log(); // ✅ 必须这样调用默认实现 // log(); // ❌ 错误:递归调用自身,非预期行为 } };

接口设计中慎用数据成员和非虚析构函数 把抽象类当接口用时(类似 Java 的
interface
),容易忽略两个隐性陷阱: 抽象类中定义了数据成员,会导致所有派生类对象大小增加,且破坏“零开销抽象”原则;接口应尽量只含纯虚函数 析构函数不是虚函数,会导致
delete
指向派生类对象的基类指针时,派生类析构函数不被调用——内存泄漏或资源未释放 务必为抽象基类声明虚析构函数,哪怕它是空的:
class Interface { public: virtual ~Interface() = default; // ✅ 推荐:= default 更清晰 virtual void do_something() = 0; };
如果基类析构函数是 protected 且 non-virtual,也可能掩盖资源管理问题,这类细节在大型继承体系里往往到上线才暴露。

相关文章