【发布时间】:2010-06-11 11:11:58
【问题描述】:
考虑下面的示例应用程序。它展示了我所说的有缺陷的类设计。
#include <iostream>
using namespace std;
struct B
{
B() : m_value(1) {}
long m_value;
};
struct A
{
const B& GetB() const { return m_B; }
void Foo(const B &b)
{
// assert(this != &b);
m_B.m_value += b.m_value;
m_B.m_value += b.m_value;
}
protected:
B m_B;
};
int main(int argc, char* argv[])
{
A a;
cout << "Original value: " << a.GetB().m_value << endl;
cout << "Expected value: 3" << endl;
a.Foo(a.GetB());
cout << "Actual value: " << a.GetB().m_value << endl;
return 0;
}
输出:
原值:1
期望值:3
实际值:4
显然,程序员被b 的常量所迷惑。错误地将b 指向this,这会产生不良行为。
我的问题:在设计 getter/setter 时应该遵循哪些 const 规则?
我的建议:如果可以通过成员函数通过引用设置成员变量,则永远不要返回对成员变量的引用。因此,要么按值返回或按值传递参数。 (无论如何,现代编译器都会优化掉多余的副本。)
【问题讨论】:
-
我不明白为什么期望值为 3。
-
@Neil:如果你不知道
A的内幕... -
预期值为 3,因为 a.Foo(B(a.GetB())) 等于 3。
-
为什么会有这么复杂的例子?在这个简单的 sn-p 中可以看到相同的效果:
int a = 1; int const& b = a; a = 4; std::cout << b;。 -
因为类中的受保护成员可以受到保护。这就是这篇文章的内容。