структура с постоянным членом - PullRequest
2 голосов
/ 10 февраля 2012

У меня проблемы с шаблонной структурой.

template<typename T>
struct A{
    const int v1;
    T* v2;
};

Моя цель - сделать v1 всегда недоступным для редактирования, тогда как v2 должен быть редактируемым, если я использую T, и не редактируемым, если я использую const T как тип.

Если я создаю конструктор для инициализации A, структура становится такой:

template<typename T>
struct A{
    const int v1;
    T* v2;
    A() : v1(-1) { v2=NULL; }
    A(int value) : v1(value) { v2=NULL; }
};

Но тогда g ++ говорит, что мне нужен определенный оператор присваивания:

ошибка: нестатический константный член "const int A :: v1", не может использовать оператор присваивания по умолчанию

Но мой оператор присваивания должен также разрешить редактирование v1. Единственное, чего я хотел бы избежать - это редактирование извне, что-то вроде:

A a;
a.v1=10;

Есть ли способ реализовать это (без создания метода получения / установки или использования указателя на новое A (int) с желаемым значением)?

Что если я объявлю v1 как const int *? Он может как-то ссылаться на какое-то значение, но не может его редактировать.

Ответы [ 4 ]

2 голосов
/ 10 февраля 2012

Вот способ «выставить» открытый, доступный только для чтения элемент данных, который можно изменять с помощью собственных функций-членов класса (включая присваивание):

template <typename T>
class Helper {
    friend class A;
    T *ptr;
    Helper &operator=(const Helper &rhs) = default; // in C++11
    Helper &operator=(const Helper &rhs) { ptr = rhs.ptr; } // in C++03
  public:
    Helper(T *ptr) : ptr(ptr) {}
    operator const int &() const { return *ptr; }
};

class A {
    int v1_;
  public:
    Helper<int> v1;
    A() : v1(&v1_) {} // although `A` should have a constructor that sets `v1_`
    A(const A &rhs) { v1_ = rhs.v1_; v1 = Helper<int>(&v1_); }
    A &operator=(const A &rhs) { v1_ = rhs.v1_; v1 = Helper<int>(&v1_); }
};

Теперь любой, кто находится вне класса A, может использовать v1, но единственное, для чего они могут его использовать, - это получить const int& ссылку на v1_.

Гораздо проще просто дать A функцию-получатель, которая возвращает const int &,но если вы действительно хотите синтаксис члена данных, то это обеспечивает его ...

2 голосов
/ 10 февраля 2012

В нем говорится, что вы не можете использовать оператор присваивания по умолчанию .Ничто не мешает вам написать свой operator= и использовать const_cast.К сожалению, это будет неопределенное поведение, так как v1 объявлено как const.Поэтому я бы посоветовал вам использовать методы доступа и личные данные.

1 голос
/ 10 февраля 2012

Вы можете просто сделать его классом со всем общедоступным (это все структура) и использовать список инициализации - нет необходимости в методах получения / установки

0 голосов
/ 10 февраля 2012

Я решил свою проблему, изменив тип v1 с int на const int *, выполнив это, я могу изменить адрес v1 и, следовательно, изменить значение, на которое указывает v1, но не допуская никакого редактирования.

Итак, вот моя новая простая структура

template<typename T>
struct A{
    const int* v1;
    T* v2;
};

Когда я использую A с типом T, я разрешаю редактировать v2, а когда я использую A с типом T const, я предотвращаю любые попытки редактировать v2указанное значение.

...