Подскажите по паттерну Состояние
От: cresta  
Дата: 04.12.11 14:01
Оценка:
Доброго времени суток!

Подскажите, пожалуйста, по реализации паттерна состояние. Делаю следующее:

// a.h
class 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. Может есть варианты лучше?

Заранее спасибо!
Re: Подскажите по паттерну Состояние
От: Centaur Россия  
Дата: 05.12.11 04:09
Оценка:
Здравствуйте, cresta, Вы писали:

C>Дело в том, что в классе Some много закрытых членов-данных и методов к которым хочется иметь доступ из классов наследников StateAbstract.


1. Подружи Some с StateAbstract.
2. Сделай в StateAbstract много protected методов для обращения к внутренностям Some.
3. …
4. Profit!
Re[2]: Подскажите по паттерну Состояние
От: cresta  
Дата: 05.12.11 08:01
Оценка:
Здравствуйте, Centaur, Вы писали:

C>2. Сделай в StateAbstract много protected методов для обращения к внутренностям Some.


Не совсем понял... А методы Some как вызывать? Указатели на методы возвращать?
Re: Подскажите по паттерну Состояние
От: MasterZiv СССР  
Дата: 05.12.11 08:06
Оценка: -1
On 12/04/2011 06:01 PM, cresta wrote:

> Подскажите, пожалуйста, по реализации паттерна состояние. Делаю следующее:


А где ты ту паттерн "Состояние" нашёл ?
Что-то не очень и похоже.

class Some {
friend class StateAbstract;

Я так понимаю, StateAbstract -- это состояние, а Some -- класс-фасад.

Зачем состоянию иметь доступ к приватной части фасада ?

Надо что-то для доступа в Some изнутри состояния -- передай в виде
параметров в каждый конкретный вызов. Лень передавать в каждый --
(может быть много параметров, неудобно) -- оформи в виде установки
контекста для действия State.

В общем, убирай friend как только возможно.

А то, что наследники друзей класса не являются друзьями класса -- это
так и есть, тут ничего не поделаешь . Т.е. надо просто проетировать
взаимоотношения классов по-другому.

friend -- зло, которое полезно только иногда, в только разумных дозах,
только по рекомендации врача.
Posted via RSDN NNTP Server 2.1 beta
Re: Подскажите по паттерну Состояние
От: johny5 Новая Зеландия
Дата: 05.12.11 09:19
Оценка:
Здравствуйте, 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; }
};


Но я просто френдил. Упрощает код. Ибо состояние объекта есть часть самого объекта и, по сути, не должно быть там каких то жёстких ограничений на доступ.

А других вариантов, вроде, нет.
Re[2]: Подскажите по паттерну Состояние
От: cresta  
Дата: 05.12.11 09:34
Оценка:
Здравствуйте, MasterZiv, Вы писали:

MZ>class Some {

MZ> friend class StateAbstract;

MZ>Я так понимаю, StateAbstract -- это состояние


Да.

MZ>, а Some -- класс-фасад.


Нет, вообще-то. Some — это Context (так в GoF назван).
Re[2]: Подскажите по паттерну Состояние
От: MasterZiv СССР  
Дата: 05.12.11 16:45
Оценка:
On 12/05/2011 01:19 PM, johny5 wrote:

> Но я просто френдил. Упрощает код. Ибо состояние объекта есть часть самого

> объекта и, по сути, не должно быть там каких то жёстких ограничений на доступ.

Кстати, хорошее С++-ное ругательство -- "нефренди" !

Типа "нефренди мне тут!"
Posted via RSDN NNTP Server 2.1 beta
Re[3]: Подскажите по паттерну Состояние
От: johny5 Новая Зеландия
Дата: 06.12.11 02:40
Оценка:
Здравствуйте, MasterZiv, Вы писали:

MZ>On 12/05/2011 01:19 PM, johny5 wrote:


>> Но я просто френдил. Упрощает код. Ибо состояние объекта есть часть самого

>> объекта и, по сути, не должно быть там каких то жёстких ограничений на доступ.

MZ>Кстати, хорошее С++-ное ругательство -- "нефренди" !


MZ>Типа "нефренди мне тут!"



friend, как и goto, да как и макросы — просто ещё один достаточно мощный оператор языка, который, правда, неумелыми руками может быть использован во зло. Но если с умом — выходит очень удобно.

Так что запрещать — не наш путь Лучше людей образовывать.
Re[4]: Подскажите по паттерну Состояние
От: MasterZiv СССР  
Дата: 06.12.11 08:01
Оценка:
On 12/06/2011 06:40 AM, johny5 wrote:

> Так что запрещать — не наш путь Лучше людей образовыват


Я говорил где-то "запрещать" ? Я как раз образовываю.
Posted via RSDN NNTP Server 2.1 beta
Re: Подскажите по паттерну Состояние
От: zakharov75 Великобритания  
Дата: 08.12.11 12:30
Оценка:
Здравствуйте, 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'.
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.