Редактировать : мой начальный удар во время моего перерыва на кофе, static const int a;
не будет работать для случая использования, который имеет в виду ОП, что подтверждают первоначальные комментарии, поэтому я переписываю и расширяю свойответ.
В большинстве случаев, когда я хочу сделать элемент класса константным, это константа, значение которой постоянно для всех времен и для всех экземпляров класса.В этом случае я использую статическую переменную const:
class Foo
{
public:
static const int a;
};
Их не нужно копировать между экземплярами, поэтому, если она будет применена, это решит вашу проблему с назначением.К сожалению, OP указал, что это не будет работать в том случае, если он имеет в виду.
Если вы хотите создать значение только для чтения , которое клиенты не могут изменять,вы можете сделать ее закрытой переменной-членом и предоставлять ее только методом const getter, поскольку в другом сообщении этой темы указано:
class Foo
{
public:
int get_a() const { return a; }
private:
int a;
};
Разница между этим и
class Foo
{
public:
const int a;
};
:
- * * * * * * * * * * * * * * * * * * * * * * * * * * * 10 * * * * * * * * * * * * * * * * * * * * * 10 10 * * * * 10 10Это означает, что назначение по праву не будет работать, так как это будет пытаться изменить значение
a
после создания объекта.(Вот почему, кстати, написание пользовательского operator=()
, который пропускает копию a
, вероятно, плохая идея с точки зрения дизайна.) - Доступ другой - вы должны скорее пройти через геттерчем доступ к члену напрямую.
На практике при выборе между этими двумя я использую элементы только для чтения.Это, вероятно, означает, что вы сможете заменить значение объекта значением другого объекта, не нарушая семантику вообще.Давайте посмотрим, как это будет работать в вашем случае.
Рассмотрим ваш объект Grid с шириной и высотой.Когда вы изначально создаете вектор, и допустим, что вы зарезервировали некоторое начальное пространство, используя vector::reserve()
, ваш вектор будет заполнен начальными по умолчанию (то есть пустыми) сетками.Когда вы идете, чтобы назначить определенную позицию в векторе, или вставляете Grid в конец вектора, вы заменяете значение объекта в этой позиции на Grid, который имеет фактический материал.Но вы можете быть в порядке с этим!Если причина, по которой вы хотели, чтобы ширина и высота были постоянными, на самом деле заключается в обеспечении согласованности между шириной и высотой и остальным содержимым вашего объекта Grid, и вы убедились, что не имеет значения, является ли ширинаи высота заменяются до или после замены других элементов Grid, тогда это назначение должно быть безопасным, потому что к концу назначения все содержимое экземпляра будет заменено, и вы вернетесь в согласованное состояние.(Если отсутствие атомарности присваивания по умолчанию было проблемой, вы, вероятно, могли бы обойти это, реализовав свой собственный оператор присваивания, который использовал конструктор копирования и операцию swap()
.)
В итоге, вы получаете, используя геттеры только для чтения, это возможность использовать объекты в векторе или любом контейнере с семантикой значений.Однако затем вы должны убедиться, что ни одна из внутренних операций Grid (или операций друзей Grid) не нарушает эту последовательность, потому что компилятор не будет блокировать ширину и высоту для вас.Это также относится к построению по умолчанию, копированию и назначению.