Подскажите, пожалуйста, по реализации паттерна состояние. Делаю следующее:
// a.hclass StateAbstract;
class Some {
friend class StateAbstract;
StateAbstract *_state;
void foo() {}
int _bar;
// еще много данных и методов
};
// a.cpp#include"a.h"class StateAbstract {
public:
virtual void func1(Some* some) { some->foo(); } // OK
};
class State1 : public StateAbstract {
public:
virtual void func1(Some *some) { some->_bar; } // error C2248: 'Some::_bar' : cannot access private member declared in class 'Some'
};
Дело в том, что в классе Some много закрытых членов-данных и методов к которым хочется иметь доступ из классов наследников StateAbstract. Можно, конечно, написать так:
class StateAbstract;
class State1;class Some {
friend class StateAbstract;
friend class State1;
StateAbstract *_state;
void foo() {}
int _bar;
};
но тогда придется делать это для каждого класса наследника StateAbstract. Может есть варианты лучше?
Здравствуйте, cresta, Вы писали:
C>Дело в том, что в классе Some много закрытых членов-данных и методов к которым хочется иметь доступ из классов наследников StateAbstract.
1. Подружи Some с StateAbstract.
2. Сделай в StateAbstract много protected методов для обращения к внутренностям Some.
3. …
4. Profit!
On 12/04/2011 06:01 PM, cresta wrote:
> Подскажите, пожалуйста, по реализации паттерна состояние. Делаю следующее:
А где ты ту паттерн "Состояние" нашёл ?
Что-то не очень и похоже.
class Some {
friend class StateAbstract;
Я так понимаю, StateAbstract -- это состояние, а Some -- класс-фасад.
Зачем состоянию иметь доступ к приватной части фасада ?
Надо что-то для доступа в Some изнутри состояния -- передай в виде
параметров в каждый конкретный вызов. Лень передавать в каждый --
(может быть много параметров, неудобно) -- оформи в виде установки
контекста для действия State.
В общем, убирай friend как только возможно.
А то, что наследники друзей класса не являются друзьями класса -- это
так и есть, тут ничего не поделаешь . Т.е. надо просто проетировать
взаимоотношения классов по-другому.
friend -- зло, которое полезно только иногда, в только разумных дозах,
только по рекомендации врача.
Здравствуйте, cresta, Вы писали:
C>Доброго времени суток!
C>class Some { C> friend class StateAbstract; C> friend class State1; C> StateAbstract *_state; C> void foo() {} C> int _bar; C>}; C>[/ccode] C>но тогда придется делать это для каждого класса наследника StateAbstract. Может есть варианты лучше?
Можно пропихивать доступ из State1 в Some конечно через базовый класс StateAbstract.
class StateAbstract
{
int GetBar() const { return some->_bar; }
int SetBar(int bar) { some->_bar = bar; }
};
Но я просто френдил. Упрощает код. Ибо состояние объекта есть часть самого объекта и, по сути, не должно быть там каких то жёстких ограничений на доступ.
On 12/05/2011 01:19 PM, johny5 wrote:
> Но я просто френдил. Упрощает код. Ибо состояние объекта есть часть самого > объекта и, по сути, не должно быть там каких то жёстких ограничений на доступ.
Здравствуйте, MasterZiv, Вы писали:
MZ>On 12/05/2011 01:19 PM, johny5 wrote:
>> Но я просто френдил. Упрощает код. Ибо состояние объекта есть часть самого >> объекта и, по сути, не должно быть там каких то жёстких ограничений на доступ.
MZ>Кстати, хорошее С++-ное ругательство -- "нефренди" !
MZ>Типа "нефренди мне тут!"
friend, как и goto, да как и макросы — просто ещё один достаточно мощный оператор языка, который, правда, неумелыми руками может быть использован во зло. Но если с умом — выходит очень удобно.
Так что запрещать — не наш путь Лучше людей образовывать.
Здравствуйте, cresta, Вы писали:
C>Доброго времени суток!
C>Подскажите, пожалуйста, по реализации паттерна состояние. Делаю следующее:
C>
C>// a.h
C>class StateAbstract;
C>class Some {
C> friend class StateAbstract;
C> StateAbstract *_state;
C> void foo() {}
C> int _bar;
C> // еще много данных и методов
C>};
C>
C>
C>// a.cpp
C>#include"a.h"
C>class StateAbstract {
C>public:
C> virtual void func1(Some* some) { some->foo(); } // OK
C>};
C>class State1 : public StateAbstract {
C>public:
C> virtual void func1(Some *some) { some->_bar; } // error C2248: 'Some::_bar' : cannot access private member declared in class 'Some'
C>};
C>
C>Дело в том, что в классе Some много закрытых членов-данных и методов к которым хочется иметь доступ из классов наследников StateAbstract. Можно, конечно, написать так:
C>
C>class StateAbstract;
C>class State1;
C>class Some {
C> friend class StateAbstract;
C> friend class State1;
C> StateAbstract *_state;
C> void foo() {}
C> int _bar;
C>};
C>
C>но тогда придется делать это для каждого класса наследника StateAbstract. Может есть варианты лучше?
C>Заранее спасибо!
I would define a special class 'SomeForState' to use it with 'StateAbstract', 'State1' and whatever state.
class SomeForState {
public:
virtual void foo() = 0;
virtual int getBar() = 0;
};
class Some : public SomeForState {
friend class StateAbstract;
StateAbstract *_state;
void foo() {} // this is a private method, you cannot invoke it directly
int getBar(){return _bar;} // this is a private method, you cannot invoke it directly
int _bar;
// еще много данных и методов
};
So, I don't think you need to use 'friend', just use a base abstract class. And, only 'StateAbstract' should 'State1' use 'SomeForState'. All others are using 'Some' and have no access to 'foo' and 'bar'.