2012-02-09 5 views
2

У меня возникли проблемы с шаблоном struct.struct with const member

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; } 
}; 

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

error: non-static const member ‘const int A::v1’, can’t use default assignment operator

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

A a; 
a.v1=10; 

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

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

+0

«без преобразования в класс-структуры (...)» У вас уже есть класс. –

+0

Вы должны понять, что в C++ struct IS является классом, просто очень специфическим типом класса. Структура - это класс, в котором все открыто. – Poodlehat

+0

Если оператор присваивания может изменять элементы 'const', то у вас все еще есть проблема * редактирования снаружи *, потому что я могу просто выполнить назначение всего объекта вместо того, чтобы самостоятельно изменять obj.v1 – Praetorian

ответ

0

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

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

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

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

1

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

+0

Это все равно не позволит назначать, не так ли? – pmr

+0

@pmr - Правильно, но если это const, я бы предпочел установить его во время ctor в любом случае. Ваше решение лучше для его вопроса. –

2

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

+0

Неужели это неопределенное поведение, если вы используете 'const_cast'? –

+1

@PaulManta Стандарт здесь совершенно ясен: 'const_cast' приводит к неопределенному поведению, если объект был ** объявлен **' const'. Это относится к переменной-члену. Я могу выкопать цитаты, если это заставляет вас чувствовать себя лучше. – pmr

+0

О, я вижу. Хорошо, что вы делаете упор на «объявленные», я бы этого не заметил. –

1

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

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_); } 
}; 

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

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

+0

Выглядит лучше, чем мое решение. Спасибо! – Vektor88

Смежные вопросы