问题描述
说我有一个 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);
}
}
这篇关于通过将非常量引用返回给成员来破坏封装的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!