Enforce use of Getter / Setter within same class (C++)
Is there a way in C++ to enforce the use of getters or setters WITHIN the class?
class C{
private:
int x; // should only be Changed by setX();
private:
setX(int i){
(...) // enforce some complicated invariantes
x = i;
};
m(){
x = 5; // should not not allowed
}
}
The only thing that comes to my mind is to put all the super-private members as private variables into an abstract base class with protected getters/setters.
But that doesn't sound like good practice.
Are there any more common ways or conventions to ensure, that everyone uses the setters?
(My purpose: If the class gets bigger i find it hard to remember what variables carry invariants with them. And currently before setting any variable I search, whether I created a getter 开发者_如何学JAVAor setter (to find out whether i have to consider invariants). But i want to get rid of this unprofessional searching-each-time.)
You can take advantage of composition like this:
class C_int
{
public:
void setX(int i)
{
/* enforce invariants */
x = i;
}
private:
int x;
};
class C
{
pulbic:
void m()
{
x.setX(5);
// x.x = 5; // Won't compile.
}
private:
C_int x;
};
But I find it odd that this is an actual problem for you, IMHO. You're the writer of the C
class and its members. You have control over how the x
variable is read/written, and x
is not part of the public interface of the class. While it is true that other people (e.g. maintainers) can write code that breaks invariants in the future, unit tests should be able to cover those cases.
a) favor accessors throughout your codebase for consistency. then you will more easily spot direct accesses to members. if you need special accessors, then create special methods:
void setFoo(const t_foo& foo) {
assert(foo.isValid());
this->d_foo = foo;
}
void invalidateFoo() {
this->d_foo = t_foo::InvalidFoo();
}
b) to get to an answer: i'll often create an inner class (temporarily in some cases):
class C {
class t_inner {
public:
/* ... */
void setX(int arg) {
/* enforce some complicated invariants... */
this->x = arg;
}
const int& getX() const {
/* ... */
return this->x;
}
private:
int x;
};
public:
/* ... */
private:
/* ... */
void m() {
this->inner().setX(5);
}
private:
t_inner d_inner;
};
The clean answer is No. There is no language feature for that; you can do some variation to achieve it, but that will clutter your code.
In Visual C++, __declspec( property )
can be used to have this feature:
__declspec(property(put=setFunction, get=getFunction)) data-type property-name;
See this article
精彩评论