Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/redis/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 通过向成员返回非常量引用来破坏封装_C++_C++11 - Fatal编程技术网

C++ 通过向成员返回非常量引用来破坏封装

C++ 通过向成员返回非常量引用来破坏封装,c++,c++11,C++,C++11,假设我有一个classFoo和一个vector数据成员,如下所示: class Foo { public: const std::vector<int> & vector() const { return vector_; } void vector(const std::vector<int> &vector) { vector_ = vector; // Other operati

假设我有一个class
Foo
和一个
vector
数据成员,如下所示:

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

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

在您的情况下,您可以只更改
someOperation()
以在一个范围内工作,而不是向量本身。然后,您的
Foo
类将需要
begin()
end()
函数,返回适当的迭代器。

在您的情况下,您可以通过将向量移出类,然后再回到类中来获得一些效率:

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_;
};
class-Foo{
公众:
std::vector&&take_vector(){
返回std::move(向量_);
}
无效向量(标准::向量向量){
向量=标准::移动(向量);
//完成后需要进行的其他操作
//向量成员已更改
}
私人:
//一些大向量
std::矢量;
};
然后

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));
    }
}
void someOperation(std::vector&v){
//在v上操作,但几乎总是让v的大小保持不变
}
int main(){
//创建Foo对象
富富,;
//长环
用于(自动k=0;k<100;k++){
//这是一个非常便宜的举动
自动v=foo.take_vector();
手术(v);
//这也是
foo.vector(std::move(v));
}
}
或者,您可以将向量上的操作构造为访问者:

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_;
};
class-Foo{
公众:
模板
无效应用操作(F&op){
op(向量!;
//完成后需要进行的其他操作
//向量成员已更改
}
私人:
//一些大向量
std::矢量;
};
这样调用:

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);
    }
}
void someOperation(std::vector&v){
//在v上操作,但几乎总是让v的大小保持不变
}
int main(){
//创建Foo对象
富富,;
//长环
用于(自动k=0;k<100;k++)
{
foo.apply_op(&someOperation);
}
}

在我看来,
someOperation
应该是
foo
对象上的操作,也就是说,它应该是
Foo
类中的一个成员函数。在我看来,如果这个向量被传入或传出类对象进行常规处理,那么你就没有任何封装可以打破。@Galik:我不确定我是否明白你的意思。如果该成员是从类外部修改的(例如,通过返回非
常量
引用),我将中断封装(还请注意,setter可能在该成员更改后执行其他操作)。我认为@RichardHodges提到的替代方法可以使更改成员更加明确,同时提高效率。下面是Visual Studio的正则表达式,它可以帮助找到返回非常量引用的方法:
(?]*>\s*)*&\s+\w+(?::\w+*\s*\(
-可能不完美,有人可以提出改进建议!相关:
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);
    }
}