user1312703
user1312703

Reputation:

Preventing creation of the of virtual method table in C++

In C# structures being value types may implement interfaces with all its benefits without size overhead, look at this snippet:

interface IMove
{
    void Move(Int32 l);
}

struct Point : IMove
{
    public Int32 x;
    public Int32 y;

    public void Move(Int32 l)
    {
        this.x += l;
        this.y += l;
    }
}

class Program
{
    static void Main(string[] args)
    {
        Console.WriteLine(Marshal.SizeOf(typeof(Int32))); // Prints "4"
        Console.WriteLine(Marshal.SizeOf(typeof(Point))); // Prints "8"
    }
}

But when I try to implement this in C++ the size of the structure becomes larger:

#include <iostream>

class IMove
{
    public:
    virtual void move(int l) = 0;
};

class Point : public IMove
{
    public:
    int x;
    int y;

    void move(int l)
    {
        this->x += l;
        this->y += l;
    }
};

int main()
{
  std::cout << sizeof(int) << "\n"; // Prints "4"
  std::cout << sizeof(Point) << "\n"; // Prints "12"
}

I think it's because of the pointer to the virtual method table. Is it possible to implement similar functionality without overhead in object size?

Upvotes: 0

Views: 79

Answers (2)

Severin Pappadeux
Severin Pappadeux

Reputation: 20130

There is Curiously Recurring Template Pattern to separate interface and implementation, no vtable needed

template <typename ToMove> struct Moveable
{
    void move()
    {
        static_cast<ToMove*>(this)->move_implementation();
    }
};

struct Point : Moveable<Point>
{
    void move_implementation()
    {
        cout << "Moving...\n";
    }
};

Upvotes: 1

rasmus
rasmus

Reputation: 3226

If you really don't want the overhead of storing the extra v-table pointer, you can always use a wrapper object before passing the point as an IMove:

struct Point { int x; int y; };

struct MoveablePoint : public IMove {
    Point& point;
    MovablePoint(Point& point) : point(point) {}
    virtual void move(int l) { point.x += l; point.y += l; }
};

Example usage:

Point point = {0};
MovablePoint movablePoint(point);
doSomething(movablePoint);

Now there's no need to store the v-table in point when you need it to persist.

Upvotes: 1

Related Questions