Принудительное использование Getter / Setter в одном классе (C++)
Есть ли способ в C++ для обеспечения использования методов получения или установки в пределах класса?
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
}
}
Единственное, что приходит мне в голову, - это поместить все суперприватные члены как частные переменные в абстрактный базовый класс с защищенными геттерами / сеттерами.
Но это не похоже на хорошую практику.
Существуют ли более распространенные способы или соглашения, гарантирующие, что каждый использует сеттеры?
(Моя цель: если класс становится больше, мне трудно вспомнить, какие переменные содержат инварианты с ними. И в настоящее время, прежде чем задавать какую-либо переменную, я ищу, создал ли я геттер или сеттер (чтобы выяснить, должен ли я учитывать инварианты). Но я хочу избавиться от этого непрофессионального поиска каждый раз.)
4 ответа
Вы можете воспользоваться композицией следующим образом:
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;
};
Но я нахожу странным, что это актуальная проблема для вас, ИМХО. Вы писатель C
класс и его члены. Вы контролируете, как x
переменная для чтения / записи, и x
не является частью открытого интерфейса класса. Хотя верно, что другие люди (например, сопровождающие) могут писать код, который нарушает инварианты в будущем, модульные тесты должны быть в состоянии охватить эти случаи.
А) отдавать предпочтение методам доступа по всей вашей кодовой базе для согласованности. тогда вам будет легче заметить прямой доступ к участникам. если вам нужны специальные методы доступа, создайте специальные методы:
void setFoo(const t_foo& foo) {
assert(foo.isValid());
this->d_foo = foo;
}
void invalidateFoo() {
this->d_foo = t_foo::InvalidFoo();
}
б) чтобы получить ответ: я часто создаю внутренний класс (временно в некоторых случаях):
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;
};
В Visual C++ __declspec( property )
может быть использован для этой функции:
__declspec(property(put=setFunction, get=getFunction)) data-type property-name;
Смотрите эту статью
Чистый ответ - нет. Для этого нет языковой функции; Вы можете сделать некоторые изменения, чтобы достичь этого, но это загромождает ваш код.