Принудительное использование Getter / Setter в одном классе (C ++) - PullRequest
2 голосов
/ 25 августа 2011

Есть ли в 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 ]

3 голосов
/ 25 августа 2011

Вы можете воспользоваться композицией, подобной этой:

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 не является частью открытого интерфейса класса.Хотя верно, что другие люди (например, сопровождающие) могут писать код, который нарушает инварианты в будущем, модульные тесты должны быть в состоянии охватить эти случаи.

1 голос
/ 25 августа 2011

а) предпочитайте методы доступа по всей вашей кодовой базе для согласованности. тогда вам будет легче заметить прямой доступ к участникам. если вам нужны специальные методы доступа, создайте специальные методы:

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;
};
0 голосов
/ 25 августа 2011

В Visual C ++ __declspec( property ) может использоваться для этой функции:

__declspec(property(put=setFunction, get=getFunction)) data-type property-name; 

См. Эту статью

0 голосов
/ 25 августа 2011

Чистый ответ: Нет .Для этого нет языковой функции;Вы можете внести некоторые изменения, чтобы добиться этого, но это загромождает ваш код.

...