在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"
}
我认为这是因为指向虚方法表的指针。是否可以在没有对象大小开销的情况下实现类似功能?
答案 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";
}
};