我想写一个包装c结构的c ++类。这是一个简单的示例,用于c结构:
struct POINT {
long x;
long y;
}
现在我假设下一节课,但我不确定它是否是"表演者"也不是很好的c ++风格。我不想使用不必要的变量或函数调用。如果你改进我的代码会非常好:)。
这个类背后的基本思想是它只是struct的包装器/处理程序。这就是为什么setStruct
和getStruct
可以直接修改私有数据并且它只是一个指针。其他成员的名称始终为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_;
}
};
}
答案 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
的成员,可以使用私有继承。您还可以提供转换运算符,以允许从Point
到POINT
的隐式转换。这将替换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
,您的类将会遇到各种问题(双删除,删除非堆内存等)。
如果您只是按值组合,那么您的课程会简单得多,也不容易出错。您可以保存一个间接级别以换取复制更多数据,但是很可能比副本可能需要两次内存的副本更好地缓存副本。
将getStruct
和setStruct
函数明确地转换为C结构和从C结构转换没有任何实际问题。
但是我的问题是:你的C ++包装器为你提供的C-struct不是什么?您只是为各个属性提供包装方法,而不是在类上执行其他操作的某种接口。在这种情况下,我根本无法看到使用包装器的原因(除非您计划向getter和setter添加调试逻辑,以便您可以更轻松地遵循程序流程。)