如何处理代理类复制赋值运算符?

时间:2010-06-25 21:12:35

标签: c++ design-patterns proxy

考虑以下代理类:

class VertexProxy
{
public:
    VertexProxy(double* x, double* y, double* z)
    : x_(x), y_(y), z_(z) {}

    VertexProxy(const VertexProxy& rhs)
    : x_(rhs.x_), y_(rhs.y_), z_(rhs.z_) {}

    // Coordinate getters
    double x() const {return *x_;}
    double y() const {return *y_;}
    double z() const {return *z_;}

    // Coordinate setters
    VertexProxy& x(double val) {*x_ = val; return *this;}
    VertexProxy& y(double val) {*y_ = val; return *this;}
    VertexProxy& z(double val) {*z_ = val; return *this;}

    VertexProxy& operator=(const VertexProxy& rhs)
    {
        // Should it be this
        x_ = rhs.x_; y_ = rhs.y_; z_ = rhs.z_;

        // or this?
        *x_ = *rhs.x_; *y_ = *rhs.y_; *z_ = *rhs.z_;

        return *this;
    }

private:
    double* x_; double* y_; double* z_;
};

我需要能够重置代理,以便它拥有不同的坐标指针(类似于boost::shared_ptr.reset()。此外,我希望能够将坐标值分配给来自不同代理的坐标值(即proxy1.assign(proxy2))。

我班上operator=的含义应该是什么?复制rhs的指针(浅拷贝)或rhs的值?或者我应该operator=私有并提供两个成员函数以避免operator=的含糊不清?

修改

好的,这是一些背景信息。我正在围绕第三方GIS库(shapelib)编写一个包装器,它将顶点坐标(x,y,z,m)存储在单独的数组中(而不是结构数组)。我的代理类用于使这个数组结构看起来更像一个结构数组。它与自定义顶点迭代器类协同工作,使得处理顶点范围变得更加容易。

Shapelib处理内存管理。我的所有代理类都在顶点数据中显示不同的“视图”。当用户使用我的代理操纵顶点坐标时,它实际上操纵了shapelib形状对象中的顶点坐标。

4 个答案:

答案 0 :(得分:3)

鉴于您的复制构造函数复制了指针,为了保持一致性,您的复制赋值运算符应该指定指针。

VertexProxy& operator=(const VertexProxy& rhs)
{
    x_ = rhs.x_;
    y_ = rhs.y_;
    z_ = rhs.z_;

    return *this;
}

如果这个(确实有问题的)代码会非常不一致:

VertexProxy test( const VertexProxy& other )
{
    double tmp1, tmp2, tmp3;
    VertexProxy p1( &tmp1, &tmp2, &tmp3 );
    p1 = other;
    return p1;
}

采取不同的行动:

VertexProxy test( const VertexProxy& other )
{
    double tmp1, tmp2, tmp3; // unused
    VertexProxy p1( other );
    return p1;
}

答案 1 :(得分:2)

这很简单。您希望VertexProxy像指针或值一样工作吗?如果你更喜欢它的作用就像一个指针,那么复制指针,如果你更喜欢它像一个值,复制值。没有人可以告诉你,你的类是一个指针或一个值(特别是因为你似乎有一些不寻常的东西)。如果你想要更好的建议,我们需要知道什么是实际的双打和原因。

快速修改: 实际上对我来说,如果你做了解除引用,你会让它像一个引用或一个指针。但是,原始观点保持不变。

答案 2 :(得分:1)

std::bitset::reference执行与VertexProxy类似的角色,可以用作模型。

typedef std::bitset<8> Bitset;
Bitset bset1, bset2;
Bitset::reference r1(bset1[3]);
Bitset::reference r2(bset2[3]);
r1 = 1;
r2 = r1;
std::cout << "bset2 = " << bset2 << "\n";
上面的

r2 = r1复制值。

答案 3 :(得分:0)

我想说这取决于对象的大小。

如果代理主题非常大,那么使用引用计数共享指针是可行的方法。只需在复制操作中复制共享指针。

如果不是那么大,那么深拷贝就更好了。每个人都不那么麻烦。