Если переменная что меняется является переменной внутренней для класса и используется только для его каких то нужд — вполне допустимо, ошибкой не назовут. Тут главное все задокументировать чтоб потом лишних вопросов не возникло
Если же это данные на которые трудно "повесить" понятие временные — то тут велик шанс что закралась какая то ошибка при проектировании/реализации данного класса и наверное стоит что то пересмотреть/переделать.
Re[2]: const метод изменяет поле класса - ошибка проектирова
Здравствуйте, Андрюха, Вы писали:
А>Спасибо ответившим.
Для "спасибо" тут есть кнопки
А> Почему foo не статический, потому что это виртуальный метод (конечно из моего первого примера это не видно)))
Ага! Это меняет дело!
А тогда ещё один вопрос. Нужно ли чтобы класс-база, этих всех виртуальных действий, был бы ещё и тем самым классом, у которого есть поле i?
А>
А> void doSomething()
А> {
А> foo(this->i);
А> cout << i << endl;
А> int m = 8;
А> foo(m);
А> cout << m << endl;
А> }
А> void foo(int &x) const
А> {
А> x += j;
А> }
А>}
А>
1) Нехорошо то, что если передать в foo, не i, а j, и выражение в foo будет позаборестее, то возможны всякие эффекты.
Я бы от этого таки как-то защитился бы. Например так:
assert( &x != &j );
2) Ничего гиперужасного в этом примере я лично не вижу, но возникает вопрос. А точно ли надо так хитро передавать поле для заполнения?
Если бы foo выглядела как
int foo( int );
и использовалась бы
this->j = this->foo( this-> j );
то вопросов бы и не возникало никаких... Кроме того, тогда принципиально нельзя бы было накрячится, передав в foo не тот объект и пункта (1) этого сообщения бы не было бы.
Точно ли этот тип так дорог в копировании?
3) Ещё, кстати есть опасность срезки всякой. Если тип i, на самом деле какой-то кудрявый и со всякими наследниками и полиморфизмом, то всё меняется.
Но, сначала, было бы хорошо понять, хотя бы, что это за тип?
Ещё лучше рассказать задачу ещё более полно/понятно. IMHO.
Я вот попробовал представить себе, зачем это могло бы быть надо. Но пока что ничего умнее читалки из файла сложного формата не придумал.
Но такую машинку я бы, конечно, делал не так. Я бы сделал отдельно читалку, вовсе не полиморфную, а отдельно разборщик формата, полиморфный. И имел бы на него указатель в читалке.
Так что хорошо бы понять что на самом деле тебе надо, тогда будет проще дать дельный совет.
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Re[2]: const метод изменяет поле класса - ошибка проектирова
On 17.06.2011 12:08, Андрюха wrote:
> # Почему foo не статический, потому что это виртуальный метод (конечно из моего > первого примера это не видно)))
А вот ЭТО уже может быть ошибкой проектирования. Виртуальными должны быть
методы, которые делают что-то С ОБЪЕКТОМ (this), а не с внешними данными.
Это конечно нестрого, но это просто как-то странно.
Лучше применять что-то типа стратегий или визиторов.
> Вопрос возник только из-за того, что инспектируя метод foo, приходишь к выводу, > что он должен быть константным. > Когда смотришь на использование этого метода, то понимаешь, что даже если он > и объявлен константным, то внутри его происходит изменение объекта...
Вообще-то, если он виртуальный, его сигнатура вместе с const уже фиксирована в
родительском классе. Если ты добавиш const, этот метод перестанет быть
реализацией виртуального класса из базового класса и станет просто перегруженным
невиртуальным методом с таким же названием и другой сигнатурой.
Posted via RSDN NNTP Server 2.1 beta
Re: const метод изменяет поле класса - ошибка проектирования
Здравствуйте, Андрюха, Вы писали:
А>Вот есть такой код А>... А>Является ли ошибкой, то, что в моей программе требуется вызывать А>
А>obj.foo(obj.i);
А>
? А>Т.е. я константным методом изменяю свой объект.
Для оценки дизайна, как минимум, нужно иметь представление о решаемой задаче и семантике класса. Из приведенного же тобой примера, как уже заметили, бросается в глаза только открытый доступ к переменной-члену i.
--
Re: const метод изменяет поле класса - ошибка проектирования
А>Является ли ошибкой, то, что в моей программе требуется вызывать А>
А>obj.foo(obj.i);
А>
?
А>Т.е. я константным методом изменяю свой объект.
А>Буду благодарен за любые комментарии и пожелания)
Правильно ли я понял: у тебя проблема в том что тебе в константном методе необходимо как то изменить переменную класса и ты хочешь выкрутиться вот таким вот хитрым способом? Если да, то для таких целей есть mutable:
class A
{
public:
A() : numberOfHits(0) { }
Data getData() const
{
numberOfHits += 1;
return Data();
}
. . . .
private:
mutableint m_numberOfHits; // Колличество обращений
};
Re: const метод изменяет поле класса - ошибка проектирования
1) Зачем Foo::foo не статический?
2) Зачем ему аргумент?
Вообще-то стремновато немного, но хорошо бы о семантике иметь представление. А то, если внутри foo есть какое-то хитрое выражение, использующее i, то при передаче ссылки на тот же i, в качестве параметра, можно получить всякие эффекты неожиданные, вплоть до UB...
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Re: const метод изменяет поле класса - ошибка проектирования
По публичному полю i. Я пытался упростить код, чтоб было легче заметить в чем суть вопроса. Ниже я привожу то, что ближе к решаемой задаче.
Про mutable я знаю. Передо мной не стоит задача измененить состояние объекта в константном методе.
Почему foo не статический, потому что это виртуальный метод (конечно из моего первого примера это не видно)))
Вопрос возник только из-за того, что инспектируя метод foo, приходишь к выводу, что он должен быть константным.
Когда смотришь на использование этого метода, то понимаешь, что даже если он и объявлен константным, то внутри его происходит изменение объекта...
К стандарту или компилятору у меня претензий нет — все вроде бы как вполне логично.
Просто интересно, как выйти из этой ситуации красиво?
#include <iostream>
using namespace std;
class FooBase
{
public:
FooBase():i(0), j(2){}
void doSomething()
{
foo(this->i);
cout << i << endl;
int m = 8;
foo(m);
cout << m << endl;
}
protected:
virtual void foo(int &x) const = 0;
int j;
private:
int i;
};
class Foo: public FooBase {
protected:
void foo(int &x) const
{
x += j;
}
};
int main() {
Foo obj;
obj.doSomething();
return 0;
}
Re[3]: const метод изменяет поле класса - ошибка проектирова
Здравствуйте, jerry_ru, Вы писали:
_>Здравствуйте, Андрюха
_>Сделай для переменной i геттер : const int& get_i() const{ return i;}
_>А потом решай новые проблеммы редизайна
А какой смысл возвращать по константной ссылке переменную интегрального типа?
Re[4]: const метод изменяет поле класса - ошибка проектирова
Здравствуйте, nen777w, Вы писали:
N>Здравствуйте, jerry_ru, Вы писали:
_>>Здравствуйте, Андрюха
_>>Сделай для переменной i геттер : const int& get_i() const{ return i;}
_>>А потом решай новые проблеммы редизайна
N>А какой смысл возвращать по константной ссылке переменную интегрального типа?
// метод не меняет содержимое объекта, const указан правильно, ошибки нет.
> > int i; > }; > > > int main() { > > Foo obj; > > cout<< "Before foo" << obj.i<< endl; > > obj.foo(obj.i); > > cout<< "After foo" << obj.i<< endl; > > return 0; > }
> Является ли ошибкой, то, что в моей программе требуется вызывать > > obj.foo(obj.i); > > ? > > Т.е. я константным методом изменяю свой объект.
Нет, не является. Метод foo у тебя меняет не свой объект, а int, переданный
в него по ссылке через параметр. То, что этим int-ом оказался мембер
того же объекта Foo -- это ответственность не метода Foo::foo, а вызывающего
этот метод кода.
То, что в твоей программе НУЖНО вызывать obj.foo(obj.i) далеко не очевидно
из приведённого кода, и не понятно, собственно, почему оно нужно, и почему
бы это было плохо. Метод Foo::foo законно константный, законно не меняет
ничего в Foo и законно меняет переданный по ссылке int.
А вот что он не использует вообще ничего из объекта Foo -- странно,
и если это не упрощение, сделанное для наглядности примера, то это -- ошибка
проектирования, в таком случае должно быть так:
static void foo(int &x);
Posted via RSDN NNTP Server 2.1 beta
Re[2]: const метод изменяет поле класса - ошибка проектирова