4

我想编写一个包装 ac struct 的 c++ 类。这是ac struct的一个简单示例:

struct POINT {
  long x;
  long y;
}

现在我假设下面这个类,但我不确定它是否是“高性能的”,也不是好的 c++ 风格。我不想使用不必要的变量或函数调用。如果您改进我的代码会非常好:)。

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

如果您使用setStruct我能想到的唯一缺点是结构可能由于范围而被删除,因此指针“无效”。

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_;
  }
};
}
4

2 回答 2

4

在这种情况下,您最好使用继承而不是组合。它将消除管理额外资源的需要,并允许您的“包装器”充当 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可以使用私有继承。您还可以提供一个转换运算符来允许从Pointto的隐式转换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)。谢克里斯提醒我。

于 2013-07-03T17:40:54.823 回答
0

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

尽管我倾向于避开它,但对类型名称使用全部大写是主观的。

如果你复制它,或者将基于堆栈的 POINT 的地址传递到setStruct.

如果你只是按值组合,你的类会简单得多,也不容易出错。您保存一定级别的间接以换取复制更多数据,但与可能必须两次访问内存的间接相比,复制的缓存可能会更好。

getStruct具有和setStruct函数显式地与 C 结构相互转换并没有任何真正的问题。

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

于 2013-07-03T17:37:11.657 回答