通过将非常量引用返回给成员来破坏封装 [英] Breaking encapsulation by returning non-const references to members

查看:57
本文介绍了通过将非常量引用返回给成员来破坏封装的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

说我有一个 Foo 类,它的数据成员是 vector _ ,像这样:

Say I have a class Foo with a vector_ data member like so:

class Foo {
public:
    const std::vector<int> & vector() const {
        return vector_;
    }
    void vector(const std::vector<int> &vector) {
        vector_ = vector;
        // Other operations which need to be done after the 
        // vector_ member has changed
    }
private:
    // Some large vector
    std::vector<int> vector_;
};

我经常遇到这样的情况

void someOperation(std::vector<int> &v) {
    // Operate on v, but almost always let v's size constant
}

int main() {
    // Create Foo object
    Foo foo;
    // Long loop
    for (auto k = 0; k < 100; k++) {
        auto v = foo.vector();
        someOperation(v);
        foo.vector(v);
    }
}

我无法通过的 foo 的(可能是很大的) vector _ 成员直接成为 someOperation 的成员,原因是( vector 方法的 const -正确)实现来访问成员。尽管 someOperation 几乎总是让其参数的大小不变,但我需要先复制向量,然后将其传递给 someOperation ,然后然后转到 foo 的设置程序。显然,如果删除 Foo 的类getter的 const -ness,则可以避免使用此多余的副本成员通过 someOperation 更改成员后,使用 afterChange 方法-但这会破坏封装:

where I can't pass foo's (possibly large) vector_ member directly to someOperation due to the (const-correct) implementation of the vector method to access the member. Although someOperation almost always lets its argument's size unchanged, I need to copy the vector first, then pass it to someOperation and then to foo's setter. Clearly, I can avoid this extra copy if I remove the const-ness of the Foo's class getter and call an afterChange method after the member has been changed by someOperation - but this breaks encapsulation:

class Foo {
public:
    std::vector<int> & vector() { // Note we now return by non-const reference
        return vector_;
    }
    void afterChange() {
        // Other operations which need to be done after the 
        // vector_ member has changed
    }
private:
    std::vector<int> vector_;
};

还有其他选择吗?还是这种破坏封装合法的情况之一?

Are there any other alternatives? Or is this one of the situations where breaking encapsulation is legitimate?

推荐答案

在您的情况下,通过移动向量可以提高效率退出课程并再次返回:

in your case you could gain some efficiency by moving the vector out of the class and back in again:

class Foo {
public:
    std::vector<int>&& take_vector() {
        return std::move(vector_);
    }

    void vector(std::vector<int> vector) {
        vector_ = std::move(vector);
        // Other operations which need to be done after the 
        // vector_ member has changed
    }
private:
    // Some large vector
    std::vector<int> vector_;
};

然后...

void someOperation(std::vector<int> &v) {
    // Operate on v, but almost always let v's size constant
}

int main() {
    // Create Foo object
    Foo foo;
    // Long loop
    for (auto k = 0; k < 100; k++) {
        // this is a very cheap move
        auto v = foo.take_vector();

        someOperation(v);

        // so is this
        foo.vector(std::move(v));
    }
}

或者您可以将向量的操作构造为a访客:

or you could structure the operation on the vector as a visitor:

class Foo {
public:
    template<class F>
    void apply_op(F&& op) {
        op(vector_);
        // Other operations which need to be done after the 
        // vector_ member has changed
    }
private:
    // Some large vector
    std::vector<int> vector_;
};

这样调用:

void someOperation(std::vector<int> &v) {
    // Operate on v, but almost always let v's size constant
}

int main() {
    // Create Foo object
    Foo foo;
    // Long loop
    for (auto k = 0; k < 100; k++) 
    {
        foo.apply_op(&someOperation);
    }
}

这篇关于通过将非常量引用返回给成员来破坏封装的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆