我有一个关于是否让类成员保持常量的问题。让我举个例子。
#include <iostream>
class ValueClass
{
int ival;
public:
void set(int i) {ival = i;}
int get() {return ival;}
};
class XXX;
class ABC
{
ValueClass vc;
public:
int getval() const {return vc.get() ;}
friend class XXX;
};
class XXX
{
std::vector<ABC> abclist;
void Invalidate()
{
// Iterates through abclist and modifies ValueClass members.
// e.g. abclist[i].vc.set(i);
}
};
class QWE
{
const ABC & abc;
public:
QWE(const ABC & abc_): abc(abc_) { }
const ABC & getABC() { return abc; }
};
int main()
{
ABC abc;
QWE qwe(abc);
std::cout << qwe.getABC().getval() << "\n"; // Compiler error
}我的ABC类包含ValueClass的一个实例,该实例负责获取int值的getter和setter。另外,QWE类有一个ABC成员,我需要获得这个成员。有人告诉我,将abc作为非常数返回是一种非常糟糕的做法。但问题来了,我不能在常量int getval()函数中使用非常数vc,也不能让它成为const,因为在另一个线程中调用了XXX::Invalidate()。此函数针对某些传入数据更改ValueClass中的数据。
显然我的设计有问题,我不能责怪C++语言。我该如何解决这个问题?
发布于 2011-03-07 23:48:50
在ValueClass中使get()常量
class ValueClass
{
int ival;
public:
void set(int i) {ival = i;}
int get() const {return ival;} // make get const
};也许应该对getABC做同样的事情
const ABC & getABC() const { return abc; } 这意味着此方法不会更改调用它的对象。
发布于 2011-03-07 23:58:00
正如其他人所指出的,访问器应该是const限定的。一般来说,如果某些东西可以是const限定的,那么它就应该是const限定的(当然,也有一些例外,例如,通过值返回的函数的返回类型不应该是const限定的,尽管这通常无关紧要)。
然而,所编写的代码还有另一个问题:它很容易不正确地使用,并意外地失去对对象生存期的跟踪。考虑一下,如果在main()中将qwe声明为:
QWE qwe(ABC());ABC()构造一个临时的ABC对象并将其传递给QWE构造器。由于构造函数参数abc_是一个const ABC&,因此它将绑定到该临时对象。然后通过初始值设定项abc(abc_)将成员引用abc绑定到临时对象。然后,构造函数返回。
构造函数返回后,临时ABC对象被销毁,qwe.abc是一个悬空引用:它不再引用对象。
如果一个类要挂起您传递给它的引用,您应该更喜欢使用参数类型的指针:这样,您就更清楚地知道,您必须关注潜在的生存期问题。此外,引用类型的类成员通常比它们的价值更混乱,因为它们使类不可赋值(因为引用本身是不可赋值的)。
发布于 2011-03-07 23:49:21
class ValueClass
{
...
int get() const {return ival;}
};
class QWE
{
...
const ABC & getABC() const { return abc; }
};你的代码必须始终保持常量,否则你会一直遇到这个问题。
https://stackoverflow.com/questions/5221691
复制相似问题