C struct的C ++类包装器

时间:2013-07-03 17:29:35

标签: c++ class oop struct wrapper

我想写一个包装c结构的c ++类。这是一个简单的示例,用于c结构:

struct POINT {
  long x;
  long y;
}

现在我假设下一节课,但我不确定它是否是"表演者"也不是很好的c ++风格。我不想使用不必要的变量或函数调用。如果你改进我的代码会非常好:)。

这个类背后的基本思想是它只是struct的包装器/处理程序。这就是为什么setStructgetStruct可以直接修改私有数据并且它只是一个指针。其他成员的名称始终为set<Attribute>get<Attribute>

如果你使用setStruct我唯一能想到的缺点是结构可能因为范围而被删除,因此指针是&#34;无效&#34;。

namespace wrapper {
class POINT {
  ::POINT * POINT_;

public:
  POINT() {
    POINT_ = new ::POINT;
  }
  ~POINT() {
    delete POINT_;
  }
  inline void setX( long x ) {
    POINT_->x = x;
  }
  inline long getX() {
    return POINT_->x;
  }
  inline void setY( long y ) {
    POINT_->y = y;
  }
  inline long getY() {
    return POINT_->y;
  }
  inline void setStruct(::POINT * __POINT) {
    POINT_ = __POINT;
  }
  inline ::POINT * getStruct() {
    return POINT_;
  }
};
}

2 个答案:

答案 0 :(得分:3)

在这种情况下,您可能最好使用继承而不是合成。它将消除管理附加资源的需要,并允许您的“包装器”充当POINT,而不是要求整个POINT结构的访问器和增变器。

namespace wrapper {
    class Point : public ::POINT
    {
    public:
        Point() { }
        ~Point() { }

        // The following accessors/mutators may not be necessary.
        // They can however be handy with code that requires a pointer to
        // member function (i.e. transformations)
        void setX(long nx) { x = nx; }
        long getX() { return x; }
        void setY(long ny) { y = ny; }
        long getY() { return y; }

        // copy assignment operators
        Point& operator=(const POINT& p)
        {
            x = p.x;
            y = p.y;
            return *this;
        }

        Point& operator=(const Point& p)
        {
            x = p.x;
            y = p.y;
            return *this;
        }
    };
}

如果要阻止直接访问POINT的成员,可以使用私有继承。您还可以提供转换运算符,以允许从PointPOINT的隐式转换。这将替换POINT* getStruct()成员函数,但仍允许您轻松地将其用于需要POINT作为参数的函数。

namespace wrapper {
    // Use private inheritance to prevent direct access to the
    // members of POINT
    class Point : private POINT
    {
    public:
        Point() { }
        ~Point() { }

        // Copy constructor
        Point(const ::POINT& p) { x = p.x; y = p.y; }

        // Accessor/mutators
        void setX(long nx) { x = nx; }
        long getX() { return x; }
        void setY(long ny) { y = ny; }
        long getY() { return y; }

        // Allow implicit conversions to POINT* when necessary
        // Replaces getStruct()
        operator ::POINT*() { return this; }
        operator const ::POINT*() const { return this; }

        // Copy assignment operators
        Point& operator=(const POINT& p)
        {
            x = p.x;
            y = p.y;
            return *this;
        }

        Point& operator=(const Point& p)
        {
            x = p.x;
            y = p.y;
            return *this;
        }
    };
}

extern "C" void someCFunction(POINT *);

int main()
{
    POINT cp;
    wrapper::Point p;

    p.x = 0; // FAIL
    p.setX(0); // OK
    p = cp; // OK

    // No need to call getPoint().
    someCFunction(p);
}

注意:我已删除inline的使用,因为它们是不必要的。类定义中定义的函数已经内联(参见$ 7.1.2 / 3)。感谢Chris提醒我。

答案 1 :(得分:0)

如前所述,_POINT是保留名称,因为它以_ +大写字母开头。

使用所有类型名称的大写是主观的,尽管我倾向于避开它。

如果您复制了类,或者将基于堆栈的POINT的地址传递给setStruct,您的类将会遇到各种问题(双删除,删除非堆内存等)。

如果您只是按值组合,那么您的课程会简单得多,也不容易出错。您可以保存一个间接级别以换取复制更多数据,但是很可能比副本可能需要两次内存的副本更好地缓存副本。

getStructsetStruct函数明确地转换为C结构和从C结构转换没有任何实际问题。

但是我的问题是:你的C ++包装器为你提供的C-struct不是什么?您只是为各个属性提供包装方法,而不是在类上执行其他操作的某种接口。在这种情况下,我根本无法看到使用包装器的原因(除非您计划向getter和setter添加调试逻辑,以便您可以更轻松地遵循程序流程。)