Подтвердить что ты не робот

Переменные класса: общедоступный доступ только для чтения, но чтение/запись в частном доступе

Whoopee, не работающий в этой библиотеке сокетов на данный момент. Я пытаюсь обучить себя немного больше на С++.

С классами, есть ли способ сделать переменную доступной только для чтения публике, но читать + писать при доступе в частном порядке? например что-то вроде этого:

class myClass {
    private:
    int x; // this could be any type, hypothetically

    public:
    void f() {
        x = 10; // this is OK
    }
}

int main() {
    myClass temp;

    // I want this, but with private: it not allowed
    cout << temp.x << endl;


    // this is what I want:

    // this to be allowed
    temp.f(); // this sets x...

    // this to be allowed
    int myint = temp.x;

    // this NOT to be allowed
    temp.x = myint;
}

Мой вопрос, скроенный, заключается в том, как разрешить полный доступ к x из f(), но доступ только для чтения из любого места, т.е. int newint = temp.x; разрешен, но temp.x = 5; не разрешен? как константная переменная, но доступная для записи из f()...

EDIT: Я забыл упомянуть, что планирую возвращать большой векторный экземпляр, используя функцию getX(), только сделает копию этого, и это не совсем оптимально. Я мог бы вернуть указатель на него, но эта плохая практика iirc.

P.S.: Где бы я опубликовал, если я просто хочу в основном показать свои знания указателей и спросить, завершено ли это или нет? Спасибо!

4b9b3361

Ответ 1

Конечно, вы можете:

class MyClass
{
    int x_;

public:
    int x() const { return x_; }
};

Если вы не хотите делать копию (для целых чисел нет накладных расходов), выполните следующие действия:

class MyClass
{
    std::vector<double> x_;

public:
    const std::vector<double>& x() const { return x_; }
};

Это не делает никакой копии. Он возвращает ссылку на const.

Ответ 2

Хотя я думаю, что функция getter, возвращающая const T&, является лучшим решением, вы можете получить почти такой синтаксис, который вы просили:

class myClass {
    private:
    int x_; // Note: different name than public, read-only interface

    public:
    void f() {
        x_ = 10; // Note use of private var
    }
    const int& x;
    myClass() : x_(42), x(x_) {} // must have constructor to initialize reference
};

int main() {
    myClass temp;

    // temp.x is const, so ...
    cout << temp.x << endl; // works
    // temp.x = 57;  // fails

}

EDIT. С прокси-классом вы можете получить именно тот синтаксис, который вы просили:

class myClass {
public:

    template <class T>
    class proxy {
        friend class myClass;
    private:
        T data;
        T operator=(const T& arg) { data = arg; return data; }
    public:
        operator const T&() const { return data; }
    };

    proxy<int> x;
    // proxy<std::vector<double> > y;


    public:
    void f() {
        x = 10; // Note use of private var
    }
};

temp.x выглядит как чтение-запись int в классе, но только для чтения int в main.

Ответ 3

Это может сделать то, что вы хотите.

Если вы хотите переменную readonly, но не хотите, чтобы клиент мог изменить способ доступа к ней, попробуйте этот шаблонный класс:

template<typename MemberOfWhichClass, typename primative>                                       
class ReadOnly {
    friend MemberOfWhichClass;
public:
    inline operator primative() const                 { return x; }

    template<typename number> inline bool   operator==(const number& y) const { return x == y; } 
    template<typename number> inline number operator+ (const number& y) const { return x + y; } 
    template<typename number> inline number operator- (const number& y) const { return x - y; } 
    template<typename number> inline number operator* (const number& y) const { return x * y; }  
    template<typename number> inline number operator/ (const number& y) const { return x / y; } 
    template<typename number> inline number operator<<(const number& y) const { return x <<y; }
    template<typename number> inline number operator>>(const number& y) const { return x >> y; }
    template<typename number> inline number operator^ (const number& y) const { return x ^ y; }
    template<typename number> inline number operator| (const number& y) const { return x | y; }
    template<typename number> inline number operator& (const number& y) const { return x & y; }
    template<typename number> inline number operator&&(const number& y) const { return x &&y; }
    template<typename number> inline number operator||(const number& y) const { return x ||y; }
    template<typename number> inline number operator~() const                 { return ~x; }

protected:
    template<typename number> inline number operator= (const number& y) { return x = y; }       
    template<typename number> inline number operator+=(const number& y) { return x += y; }      
    template<typename number> inline number operator-=(const number& y) { return x -= y; }      
    template<typename number> inline number operator*=(const number& y) { return x *= y; }      
    template<typename number> inline number operator/=(const number& y) { return x /= y; }      
    template<typename number> inline number operator&=(const number& y) { return x &= y; }
    template<typename number> inline number operator|=(const number& y) { return x |= y; }
    primative x;                                                                                
};      

Пример использования:

class Foo {
public:
    ReadOnly<Foo, int> x;
};

Теперь вы можете получить доступ к Foo.x, но вы не можете изменить Foo.x! Помните, что вам нужно добавить и побитовые и унарные операторы! Это просто пример, чтобы начать работу

Ответ 4

Существует способ сделать это с помощью переменной-члена, но, вероятно, это не рекомендуется.

Имейте приватный член, который доступен для записи, и переменную открытого элемента const, которая псевдонизирует член своего класса.

class Foo
{
  private:
      Bar private_bar;

  public:
      const Bar& readonly_bar; // must appear after private_bar
                              // in the class definition

  Foo() :
       readonly_bar( private_bar )
  {
  }
};

Это даст вам то, что вы хотите.

void Foo::someNonConstmethod()
{
    private_bar.modifyTo( value );
}

void freeMethod()
{
    readonly_bar.getSomeAttribute();
}

Что вы можете делать, и что вам нужно делать, это разные вопросы. Я не уверен, что метод, который я только что изложил, популярен и передаст много обзоров кода. Он также излишне увеличивает sizeof (Foo) (хотя и на небольшое количество), тогда как простой аксессуар "getter" не будет и может быть встроен, поэтому он также не будет генерировать больше кода.

Ответ 5

Вам нужно будет оставить его закрытым, а затем сделать функцию для доступа к значению;

private:

    int x;

public:

    int X()
    {
        return x;
    }

Ответ 6

Напишите публичную функцию getter.

int getX(){ return x; }

Ответ 7

Вам нужно сделать член private и предоставить метод public getter.

Ответ 8

Единственный способ, которым я знаю предоставление доступа только для чтения к частным данным в классе С++, - это публичная функция. В вашем случае это будет выглядеть следующим образом:

int getx() const { return x; }

или

int x() const { return x; }.

При создании частного элемента данных вы по умолчанию делаете его невидимым (a.k.a без доступа) к области вне класса. По сути, члены класса имеют доступ для чтения/записи к частному члену данных (при условии, что вы не указываете его как const). friend класса получают доступ к частным данным.

Обратитесь здесь и/или любую хорошую книгу С++ о спецификаторах доступа.

Ответ 9

но temp.x = 5; не допускается?

Это любой способ, который не разрешен в опубликованном фрагменте, поскольку он объявлен как закрытый и может быть доступен только в пределах класса.

Здесь запрашивается доступ к

cout < temp.x < епсИ;

но здесь не для -

int myint = temp.x;

Это звучит очень противоречиво.

Ответ 10

Вы можете захотеть сопоставить С# свойства для доступа (в зависимости от того, что вы собираетесь делать, для предполагаемой среды и т.д.).

class Foo
{
  private:
    int bar;

  public:
    __declspec( property( get = Getter ) ) int Bar;

    void Getter() const
    {
      return bar;
    }
}

Ответ 11

Простое решение, такое как Rob, но без конструктора:

class myClass {
    private:
    int m_x=10; // Note: different name than public, read-only interface
    public:
    const int& x=m_x;

};

int main() {
    myClass temp;

    // temp.x is const, so ...
    cout << temp.x << endl; // works
    // temp.x = 57;  // fails

}

Это похоже на метод get, но короче. Интересный вопрос... что-то вроде. член const const bool; может сэкономить много геттеров... но я не знаю языков с этой функцией...