防止在C ++中创建虚方法表

时间:2015-03-08 22:33:51

标签: c# c++

在C#结构中,值类型可以实现具有所有优点的接口,而不会产生大小开销,请看这个片段:

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"
    }
}

但是当我尝试在C ++中实现它时,结构的大小变得更大:

#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"
}

我认为这是因为指向虚方法表的指针。是否可以在没有对象大小开销的情况下实现类似功能?

2 个答案:

答案 0 :(得分:1)

如果你真的不想要存储额外的v-table指针的开销,你可以在将点作为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; }
};

使用示例:

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

现在没有必要在需要时保存v-table。

答案 1 :(得分:1)

有奇怪的重复模板模式来分离界面和实现,不需要vtable

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

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