I'm a beginner in C++ and I can't understand why C++ uses virtual tables to implement polymorphism instead of simple function pointers.

Let's consider an example:

struct Shape {
    virtual double area() = 0;
};

struct Square: public Shape {
    virtual double area();
    /* ... */
};

struct Circle: public Shape {
    virtual double area();
    /* ... */
};

double f(Shape &s) { return 42.0 + s.area(); }

How C++ usually (always?) implements the polymorphism: Shape and every derived class has the hidden pointer to a virtual table as the first element. When s.area() is called, the pointer to the corresponding area function is taken from the virtual table of s.

But if I don't know about C++ and virtual tables and want to realize such polymorphism in C, I would do it like this:

struct Shape {
    double (*area)(struct Shape *this);
};

struct Square {  /* is a Shape */
    double (*area)(struct Square *this);
    /* ... */
};

struct Circle {  /* is a Shape */
    double (*area)(struct Circle *this);
    /* ... */
};

double f(struct Shape *s) { return 42.0 + s->area(s); }

double cirlce_area(struct Circle *this);
double square_area(struct Square *this);

/* ... */

struct Circle c = { &circle_area, ... };
printf("%f", f((struct Shape *)c));

When s->area() is called, the first pointer from the s structure used.

Why does C++ use virtual tables instead of just place pointers to virtual functions at the beginning of the structure (with the same order)? I can't currently find any reason why the last approach may not work.

有帮助吗?

解决方案

Conceptually, it is the very same thing.

The virtual method table is nothing than a list of function pointers. It is not integrated in the object itself because it is static for the class of the object, so it can be shared among instances of the same class (saving computation power during initialization and memory during the objects whole lifetime).

In C++ specifically, each constructor sets the Virtual Method Table pointer to the pointer of the class to which it belongs. Thus, after the outermost constructor ran, the virtual methods resolve to the class of which the object is.

其他提示

Consider what would happen with a class that contains many virtual methods: you would have to pay the cost of storing X function pointers separately for each instance. That could become very wasteful very quickly.

Using a vptr can also help implement other language features: it's easy to use the value of the vptr to determine what the runtime type of an object is (think of typeid).

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top