1.虚函数

虚函数是 C++ 中支持 动态多态 的关键机制之一。它允许通过基类的指针或引用调用派生类中的重写函数,而不管指针或引用的类型是什么。虚函数在基类中使用 virtual 关键字声明,并且可以在派生类中进行重写。


#include <iostream>
using namespace std;

class Base {
public:
    virtual void show() {  // 基类中的虚函数
        cout << "Base class show() called." << endl;
    }
};

class Derived : public Base {
public:
    void show() override {  // 派生类重写虚函数
        cout << "Derived class show() called." << endl;
    }
};

int main() {
    Base* basePtr;
    Derived derivedObj;

    basePtr = &derivedObj;
    basePtr->show();  // 输出:Derived class show() called.

    return 0;
}

普通虚函数:

  • 如果派生类没有重写该函数,它会继承基类的实现。

  • 如果派生类重写了该函数,它会覆盖基类的实现。

纯虚函数:

如果基类有纯虚函数,派生类必须提供一个实现,否则派生类也会变成抽象类,不能实例化。

特性 普通虚函数 纯虚函数
定义 提供默认实现,派生类可以选择覆盖 不提供实现,必须在派生类中实现
是否可以实例化基类 可以实例化基类对象,除非类中有纯虚函数 不能实例化基类对象,类为抽象类
派生类要求 派生类可以选择是否重写普通虚函数 派生类必须重写纯虚函数,除非派生类本身为抽象类
多态 支持多态,通过基类指针/引用调用派生类实现 同样支持多态,但派生类必须实现纯虚函数
用途 用于提供默认行为或接口 用于定义接口,强制派生类实现

虽然拥有纯虚函数的抽象类无法实例化,但是可以使用指针指向派生类,代码如下:

#include <iostream>

class Shape {
public:
    // 纯虚函数,强制派生类必须实现
    virtual void draw() = 0;

    virtual ~Shape() = default;  // 虚析构函数,确保派生类能正确析构
};

class Circle : public Shape {
public:
    void draw() override {
        std::cout << "Drawing Circle" << std::endl;
    }
};

class Square : public Shape {
public:
    void draw() override {
        std::cout << "Drawing Square" << std::endl;
    }
};

int main() {
    // 使用基类指针指向派生类对象
    Shape* shape1 = new Circle();   // 基类指针指向派生类对象
    Shape* shape2 = new Square();   // 基类指针指向另一个派生类对象

    // 调用派生类的重写方法,发生多态
    shape1->draw();  // 输出:Drawing Circle
    shape2->draw();  // 输出:Drawing Square

    // 清理资源
    delete shape1;
    delete shape2;

    return 0;
}

2.虚继承

虚继承是解决 菱形继承问题 的一种机制。菱形继承问题发生在多重继承中,当一个派生类同时继承两个类的相同基类时,会导致该基类的成员变量和函数被多次继承,形成多余的冗余数据和不必要的复杂性。

#include <iostream>
using namespace std;

class A {
public:
    A() { cout << "A constructor" << endl; }
    void show() { cout << "Class A" << endl; }
};

class B : virtual public A {
public:
    B() { cout << "B constructor" << endl; }
};

class C : virtual public A {
public:
    C() { cout << "C constructor" << endl; }
};

class D : public B, public C {
public:
    D() { cout << "D constructor" << endl; }
};

int main() {
    D obj;  // 只会调用 A 构造函数一次
    obj.show();  // 输出:Class A

    return 0;
}
  • 虚继承要求虚基类的构造函数只能由最派生类的构造函数调用。

  • 这样保证了虚基类的构造只会执行一次,避免了重复构造的问题。

3.虚基类

虚基类是虚继承的基础。当一个类通过虚继承继承另一个类时,继承的那个类就被称为虚基类。虚基类确保在继承层次结构中,基类对象只有一份。

4.虚类

#include <iostream>

class Shape {
public:
    // 纯虚函数
    virtual void draw() = 0; 

    // 析构函数通常也会被声明为虚函数
    virtual ~Shape() = default;
};

class Circle : public Shape {
public:
    void draw() override {
        std::cout << "Drawing Circle" << std::endl;
    }
};

class Square : public Shape {
public:
    void draw() override {
        std::cout << "Drawing Square" << std::endl;
    }
};

int main() {
    // Shape s; // 错误:不能实例化抽象类
    Shape* shape = new Circle();
    shape->draw();  // 输出:Drawing Circle

    delete shape;
    shape = new Square();
    shape->draw();  // 输出:Drawing Square

    delete shape;
    return 0;
}

Logo

Agent 垂直技术社区,欢迎活跃、内容共建。

更多推荐