当前位置:首页 C++ > 正文

C++ 虚函数基础知识之虚函数表指针什么时候初始化

作者:野牛程序员:2023-08-01 16:57:13 C++阅读 2913

在C++中,虚函数表指针(vptr)是由编译器在具有虚函数的类对象的构造过程中进行初始化的。虚函数表指针的初始化发生在以下两种情况下:

  1. 对象的构造过程:在创建一个包含虚函数的类对象时,编译器会在对象的内存布局中分配内存,并在对象的开头或结尾处添加一个指向虚函数表的指针(vptr)。然后,编译器会在构造函数中设置该虚函数表指针的值,使其指向类的虚函数表。这样,在对象创建时,虚函数表指针就被正确初始化了。

  2. 虚函数表指针的更新:当从一个类派生出新的派生类时,新派生类可能会重写基类的虚函数,或者可能会添加新的虚函数。在这种情况下,编译器会生成适当的虚函数表,并在派生类的构造函数中更新虚函数表指针,以使其指向派生类的虚函数表。这确保了正确的虚函数调用,即使通过基类指针或引用来调用派生类的虚函数。

需要注意的是,在构造函数和析构函数中,虚函数表指针的值可能还没有被完全设置或者已经被销毁,这是因为在构造函数和析构函数的执行期间,对象可能只是部分构造或部分销毁。因此,在构造函数和析构函数中调用虚函数可能不会得到期望的结果,并且应该避免这样的调用。

虚函数表指针的初始化和更新是C++实现多态性的基础,它确保了在运行时正确地调用适当的虚函数,从而实现了多态的行为。

下面是一个简单的C++代码示例,演示了虚函数表指针的初始化和使用:

#include <iostream>

class Shape {
public:
    virtual void draw() {
        std::cout << "Drawing a shape." << std::endl;
    }
};

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

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

int main() {
    Shape* shape1 = new Circle();
    Shape* shape2 = new Square();

    // Calling draw() using the Shape pointers
    shape1->draw(); // Output: "Drawing a circle."
    shape2->draw(); // Output: "Drawing a square."

    delete shape1;
    delete shape2;

    return 0;
}

在这个示例中,我们定义了一个基类 Shape 和两个派生类 CircleSquare,并在其中重写了虚函数 draw(). Shape 类中的 draw() 函数声明为虚函数,这表明它是一个虚函数,允许在派生类中进行函数的重写。

main 函数中,我们创建了两个 Shape 类型的指针 shape1shape2,并用 new 运算符分别创建了 CircleSquare 类型的对象,并将它们赋值给相应的指针。这时,对象的内存布局中会包含虚函数表指针,指向对应类的虚函数表。

在接下来的代码中,我们通过基类指针调用了虚函数 draw()。由于虚函数表指针已经正确初始化,程序会在运行时动态地调用正确的虚函数版本,即使是通过基类指针来调用。

输出结果为:

Drawing a circle.
Drawing a square.

这个例子展示了虚函数表指针的初始化和使用,允许我们在运行时实现多态行为,即根据对象的实际类型来调用相应的虚函数。

野牛程序员教少儿编程与信息学奥赛-微信|电话:15892516892
野牛程序员教少儿编程与信息学竞赛-微信|电话:15892516892
相关推荐

最新推荐

热门点击