问题的背景:
C++ 支持面向对象编程,这是现代语言的基础。为了实现多态性,使用了虚函数。这允许在运行时而不仅仅是在编译时调用所需的方法实现,这对具有继承结构的架构至关重要。
问题:
常见的错误是混淆静态方法调用和动态方法调用,忘记虚析构函数,错误处理继承(例如对象切片,调用基类版本而不是覆盖版本)。通常会混淆何时真正工作多态性。
解决方案:
虚函数在基类中使用关键字 virtual 声明,可以在派生类中重写(override)。如果通过指针或对基类的引用调用函数,将执行派生类中的版本。
代码示例:
struct Base { virtual void foo() { std::cout << "Base::foo "; } }; struct Derived : Base { void foo() override { std::cout << "Derived::foo "; } }; void call(Base& b) { b.foo(); } int main() { Derived d; call(d); // 输出 Derived::foo }
关键特点:
通过值传递对象时多态性是否有效?
不。通过值传递导致 "切片"——只复制与参数类型相关的部分(通常是基类),多态性被关闭。
代码示例:
void call(Base b) { b.foo(); } // 总是调用 Base::foo
需要在基类中将析构函数声明为虚的吗?
是的,如果通过指向基类的指针删除派生对象。否则,会导致内存泄漏或资源未释放。
代码示例:
struct Base { virtual ~Base() {} };
如果不在子类中使用关键字 override 会发生什么?
如果在派生类中没有指定 override,但错误地更改了函数签名(例如,遗漏 const 或参数错误),则函数不会覆盖虚函数,而是创建新函数,多态性不会按预期工作。
程序员未将基类的析构函数声明为虚;通过基类指针删除对象数组导致内存泄漏。
优点:
缺点:
声明了虚析构函数;仅使用基类型的引用/指针。多态性正常工作。
优点:
缺点: