一、虚函数

虚函数是用于实现多态性的一种机制。它允许通过基类指针或引用调用派生类中的重写版本。通过将函数声明为虚函数,C++ 提供了一种在运行时决定调用哪个函数的方法。

特点

语法

class Base {
public:
    virtual void show() { std::cout << "Base class show function\n"; }
    virtual ~Base() {} // 虚析构函数
};

class Derived : public Base {
public:
    void show() override { std::cout << "Derived class show function\n"; }
};
  • 使用 virtual 关键字:在基类中使用 virtual 关键字声明虚函数,派生类可以重写该函数。
  • 运行时绑定:通过基类指针或引用调用虚函数时,实际调用的是派生类中重写的版本。
  • 虚析构函数:如果类包含虚函数,通常应该有一个虚析构函数,以确保正确释放派生类的资源。

示例:

#include <iostream>

class Base {
public:
    virtual void show() { std::cout << "Base class show function\n"; }
    virtual ~Base() {}
};

class Derived : public Base {
public:
    void show() override { std::cout << "Derived class show function\n"; }
};

void display(Base* b) {
    b->show(); // 调用的是实际对象的 show 函数
}

int main() {
    Base* b = new Derived();
    display(b); // 输出:Derived class show function
    delete b; // 先调用 Derived 的析构函数,再调用 Base 的析构函数
    return 0;
}

不使用虚函数会有什么问题

不使用虚函数,无法实现运行时多态性。这意味着你不能通过基类指针或引用来调用派生类的重写方法。所有方法调用都将在编译时确定,限制了对象之间的灵活交互。

示例:

class Base {
public:
    void show() {
        std::cout << "Base class\n";
    }
};

class Derived : public Base {
public:
    void show() { // 此处不是重写,而是隐藏 注释1
        std::cout << "Derived class\n";
    }
};

void display(Base* b) {
    b->show(); // 始终调用 Base::show()
}

int main() {
    Base b;
    Derived d;
    display(&b); // 输出:Base class
    display(&d); // 仍然输出:Base class
    d.show();    // 输出:Derived class
    return 0;
}

在这个例子中,即使 display 函数接收的是 Derived 类的对象,也只会调用 Base 类的方法。实际上我想调用的是 Derived 类中的 show 方法

什么是隐藏?

隐藏是指当派生类定义了一个与基类同名的非虚函数(或静态成员函数)时,基类的同名函数会被“隐藏”,但不会被覆盖。这意味着,如果你使用基类指针或引用来调用函数,基类的方法仍然会被调用。

二、纯虚函数

纯虚函数是一种特殊的虚函数,它在基类中没有实现,只有声明。要求派生类必须重写该函数(如果派生类不实现改函数那么派生类也是个抽象类不能被实例化)。包含纯虚函数的类称为抽象类,无法直接实例化。(和 java 中的抽象方法类似)

特点

  • 语法

    class Abstract {
    public:
        virtual void show() = 0; // 纯虚函数
    };
    
  • 使用 = 0 语法:在虚函数声明后添加 = 0 表示该函数是纯虚函数。

  • 抽象类:如果一个类包含至少一个纯虚函数,该类就是抽象类,不能实例化。

  • 派生类实现:派生类必须实现所有纯虚函数才能实例化。

示例:

#include <iostream>

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

class Concrete : public Abstract {
public:
    void show() override { std::cout << "Concrete class show function\n"; }
};

int main() {
    // Abstract a; // 错误:无法实例化抽象类
    Concrete c;
    c.show(); // 输出:Concrete class show function
    return 0;
}

总结

  • 虚函数:提供多态性,增强代码灵活性。适用于需要不同实现但使用相同接口的场景。
  • 纯虚函数:用于定义接口,强制派生类实现特定功能。适用于设计模式、框架开发和插件架构等需要接口的场景。(java 中的抽象函数)

点赞(0) 打赏

评论列表 共有 0 条评论

暂无评论

微信公众账号

微信扫一扫加关注

发表
评论
返回
顶部