Виртуальное наследование, что будет в таком случае...?
От: Srv  
Дата: 25.09.07 04:18
Оценка:
Добрый день!
Есть класс

class CEventHandler
{
public:
    CEventHandler() {};
    ~CEventHandler() {};

    virtual    void        OnAccept(PCLIENT_INFO pclient) {};
    virtual    void        OnDisconnect(PCLIENT_INFO pclient) {};
    virtual    int            OnRead(PCLIENT_INFO pclient, uchar* pinbuf, ulong inbufsize, uchar** poutbuf, ulong* poutbufsize) {return -1;};
    virtual    int            OnIdle(PCLIENT_INFO pclient) {return -1;};
    virtual    void        OnSend(PCLIENT_INFO pclient) {};
};


Есть другой класс..


class CRemoteUser : public CEventHandler
{
public:
    CRemoteUser();
    ~CRemoteUser();

    int                        Init(ushort port, CIndexWriterReader *pindexwr, CErrorLog *perrorlog, CWave *pwave, CSettings *psets);
    void                    Done(void);

    virtual    void            OnAccept(PCLIENT_INFO pclient);
    virtual    void            OnDisconnect(PCLIENT_INFO pclient);
    virtual    int                OnRead(PCLIENT_INFO pclient, uchar* pinbuf, ulong inbufsize, uchar** poutbuf, ulong* poutbufsize);
    virtual    int                OnIdle(PCLIENT_INFO pclient);
    virtual    void            OnSend(PCLIENT_INFO pclient);

private:
};


Мне необходимо "упрятать" CEventHandler в CRemoteUser ...
Дак вот вопросы..
1. Что будет если я сделаю наследование не так: class CRemoteUser : public CEventHandler, а class CRemoteUser : private CEventHandler и переопределю в private секции CRemoteUser OnAccept, OnDisconnect и т.д.?
2. Если я все так и оставлю в классе CRemoteUser в секции public OnAccept, OnDisconnect и т.д., а изменю только class CRemoteUser : private CEventHandler... какие методы будут вызываться в данном случае (public или private)?

Спасибо!
Re: Виртуальное наследование, что будет в таком случае...?
От: Srv  
Дата: 25.09.07 04:20
Оценка:
Здравствуйте, Srv, Вы писали:

Извиняюсь не "Виртуальное наследование..." конечно же... ну суть должна быть ясна.
Re: Виртуальное наследование, что будет в таком случае...?
От: _Dreamer Россия  
Дата: 25.09.07 04:44
Оценка:
Здравствуйте, Srv, Вы писали:

Srv>Добрый день!

Srv>Есть класс

Srv>Мне необходимо "упрятать" CEventHandler в CRemoteUser ...

Srv>Дак вот вопросы..
Srv>1. Что будет если я сделаю наследование не так: class CRemoteUser : public CEventHandler, а class CRemoteUser : private CEventHandler и переопределю в private секции CRemoteUser OnAccept, OnDisconnect и т.д.?
Srv>2. Если я все так и оставлю в классе CRemoteUser в секции public OnAccept, OnDisconnect и т.д., а изменю только class CRemoteUser : private CEventHandler... какие методы будут вызываться в данном случае (public или private)?

Srv>Спасибо!


а что значит — "упрятать" ?

по вопросам —
struct base
{
public :

    virtual void virt_method() { printf("base::virt_method()\n"); }
};

struct s1 : public base 
{
public :

    virtual void virt_method() { printf("s1::virt_method()\n"); }
};

struct s2 : private base 
{
public :

    virtual void virt_method() { printf("s2::virt_method()\n"); }
};

struct s3 : public base 
{
private :

    virtual void virt_method() { printf("s3::virt_method()\n"); }
};

//...

base * ptr = NULL;
base b;
s1 s1_;
s2 s2_;
s3 s3_;

ptr = &b;
ptr->virt_method(); // "base::virt_method()"

ptr = &s1_;
s1_.virt_method();  // "s1::virt_method()"
ptr->virt_method(); // "s1::virt_method()"

ptr = &s2_; /* нет доступа к предку */
s2_.virt_method(); // "s2::virt_method()"
ptr->virt_method();

ptr = &s3_;
s3_.virt_method(); /* нет доступа к методу самого класса */
ptr->virt_method(); // "s3::virt_method()"
Re[2]: Виртуальное наследование, что будет в таком случае...
От: Srv  
Дата: 25.09.07 05:38
Оценка:
Здравствуйте, _Dreamer, Вы писали:


_D>а что значит — "упрятать" ?


Значит что кроме как этого класса (CRemoteUser) и класса что вызывает методы CEventHandler (OnAccept, OnDisconnect и т.д.) ни кто не смог обратиться к методам CEventHandler.
Re[3]: Виртуальное наследование, что будет в таком случае...
От: Erop Россия  
Дата: 25.09.07 06:16
Оценка:
Здравствуйте, Srv, Вы писали:

Srv>Значит что кроме как этого класса (CRemoteUser) и класса что вызывает методы CEventHandler (OnAccept, OnDisconnect и т.д.) ни кто не смог обратиться к методам CEventHandler.


1) Чтобы у твоего наследника нельзя было звать методы интерфейса, объяви их в наследнике, как private

2) Чтобы наследник нельзя было привести к базе, используй private базу. Но тебе надо понять кто и когда сможет выполнить этопреобразование, или откуда-то ещё (например благодаря саморегистрации базы) получить указатель на базу.

3) Если ты хочешь чтобы у базы никто, кроме выделенных каких-то пользователей не позвал методы, то надо использовать friend классы видимо, хотя, ИМХО, лучше описать задачу поподробнее, а то какая-то нужда подозрительная.
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Re[4]: Виртуальное наследование, что будет в таком случае...
От: Srv  
Дата: 25.09.07 06:30
Оценка:
Здравствуйте, Erop, Вы писали:

E>3) Если ты хочешь чтобы у базы никто, кроме выделенных каких-то пользователей не позвал методы, то надо использовать friend классы видимо, хотя, ИМХО, лучше описать задачу поподробнее, а то какая-то нужда подозрительная.


Просто есть еще класс

class CServer
{
public:
    CServer();
    ~CServer();

    int                        CreateServer(ushort port, CEventHandler *pevent) {m_pevent = pevent; return 0;};
    void                    DestroyServer(void);
private:
    CEventHandler            *m_pevent;
};



Который и вызывает переопределенные методы в CRemoteUser и "сигналит" ему о тех или иных событиях. Дак вот кроме него ни кто не должен вызывать эти переопределенные методы в CRemoteUser (OnAccept, OnDisconnect...).
Re[5]: Виртуальное наследование, что будет в таком случае...
От: Erop Россия  
Дата: 25.09.07 12:13
Оценка: 2 (1)
Здравствуйте, Srv, Вы писали:

Srv>Просто есть еще класс


Srv>
Srv>class CServer
Srv>    int                        CreateServer(ushort port, CEventHandler *pevent) {m_pevent = pevent; return 0;};
Srv>    void                    DestroyServer(void);
Srv>


Ну сделай так, например:
class CServer
{
public:
    CServer();
    ~CServer();

        class IEventHandler
        {
            virtual void OnAccept(PCLIENT_INFO pclient) = 0;
            virtual void OnDisconnect(PCLIENT_INFO pclient) = 0;
            virtual int OnRead(PCLIENT_INFO pclient, uchar* pinbuf, 
                        ulong inbufsize, uchar** poutbuf, ulong* poutbufsize) = 0;
            virtual int OnIdle(PCLIENT_INFO pclient) = 0;
            virtual void OnSend(PCLIENT_INFO pclient) = 0;
            friend class CServer;
// Дальше всё как у тебя, но
private:
    IEventHandler            *m_pevent;
};


Ну а CEventHandler выводишь из IEventHandler, ну и реализацию методов объявляешь в private секции...
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Re[6]: Уточню
От: Erop Россия  
Дата: 25.09.07 12:23
Оценка:
E>Ну а CEventHandler выводишь из IEventHandler, ну и реализацию методов объявляешь в private секции...

Но намного прямее будет, если ты разработаешь интерфейс имеющий самостоятельную семантику, то есть не привязанный непосредственно к CServer, и будешь публиковать этот интерфейс и использовать так или сяк, например, в том числе, и в сервере
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Re[6]: Виртуальное наследование, что будет в таком случае...
От: Srv  
Дата: 26.09.07 02:53
Оценка:
Здравствуйте, Erop, Вы писали:
E>Ну сделай так, например:
E>
E>class CServer
E>{
E>public:
E>    CServer();
E>    ~CServer();

E>        class IEventHandler
E>        {
E>            virtual void OnAccept(PCLIENT_INFO pclient) = 0;
E>            virtual void OnDisconnect(PCLIENT_INFO pclient) = 0;
E>            virtual int OnRead(PCLIENT_INFO pclient, uchar* pinbuf, 
E>                        ulong inbufsize, uchar** poutbuf, ulong* poutbufsize) = 0;
E>            virtual int OnIdle(PCLIENT_INFO pclient) = 0;
E>            virtual void OnSend(PCLIENT_INFO pclient) = 0;
E>            friend class CServer;
E>// Дальше всё как у тебя, но
E>private:
E>    IEventHandler            *m_pevent;
E>};

E>


E>Ну а CEventHandler выводишь из IEventHandler, ну и реализацию методов объявляешь в private секции...


Я сделал так, насколько это правильно?


class CServer;
class IEventHandler
{
    virtual    void        OnAccept(PCLIENT_INFO pclient) = 0;
    virtual    void        OnDisconnect(PCLIENT_INFO pclient) = 0;
    virtual    int         OnRead(PCLIENT_INFO pclient, uchar* pinbuf, ulong inbufsize, uchar** poutbuf, ulong* poutbufsize) = 0;
    virtual    int         OnIdle(PCLIENT_INFO pclient) = 0;
    virtual    void        OnSend(PCLIENT_INFO pclient) = 0;
    friend class CServer;
};

class CServer
{
public:
    CServer();
    ~CServer();

    int                     CreateServer(ushort port, IEventHandler *pevent) {m_pevent = pevent; return 0;};
    void                    DestroyServer(void);
private:
    IEventHandler           *m_pevent;
};

class CRemoteUser : private IEventHandler
{
public:
    CRemoteUser();
    ~CRemoteUser();

    int                     Init(ushort port, CIndexWriterReader *pindexwr, CErrorLog *perrorlog, CWave *pwave, CSettings *psets);
    void                    Done(void);

private:
    virtual    void            OnAccept(PCLIENT_INFO pclient);
    virtual    void            OnDisconnect(PCLIENT_INFO pclient);
    virtual    int             OnRead(PCLIENT_INFO pclient, uchar* pinbuf, ulong inbufsize, uchar** poutbuf, ulong* poutbufsize);
    virtual    int             OnIdle(PCLIENT_INFO pclient);
    virtual    void            OnSend(PCLIENT_INFO pclient);
};


В CRemoteUser::Init я создаю CServer::CreateServer(..., this)
Re[7]: Виртуальное наследование, что будет в таком случае...
От: Erop Россия  
Дата: 26.09.07 14:02
Оценка:
Здравствуйте, Srv, Вы писали:

Srv>Я сделал так, насколько это правильно?

Ну более или менее, но вторйо путь всё равно лучше, на самом деле.
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Re[8]: Виртуальное наследование, что будет в таком случае...
От: Srv  
Дата: 26.09.07 17:14
Оценка:
Здравствуйте, Erop, Вы писали:

E>Здравствуйте, Srv, Вы писали:


Srv>>Я сделал так, насколько это правильно?

E>Ну более или менее, но вторйо путь всё равно лучше, на самом деле.

А я не сильно обнаглею если спрошу как примерно это сделать, а то не совсем понятно?
Re[9]: А что тут не понятно?
От: Erop Россия  
Дата: 26.09.07 19:05
Оценка:
Здравствуйте, Srv, Вы писали:

Srv>А я не сильно обнаглею если спрошу как примерно это сделать, а то не совсем понятно?


А что тут не понятно
Автор: Erop
Дата: 25.09.07
?

Ну думаешь какой бы мог быть интерфейс, если бы сервер был не один, а три разных. Чтобы от него абстрагироваться, описываешь его, в своём хендлере реализуешь, а при регистрации хендлера в сервере отдаёшь туда интерфейс.

Плюсы такие что нет нужды привязываться как-то к конкретному серверу. И Серверу нет нужды привязываться к конкретному хендлеру. Всё что их связывает -- это хорошо формализованый и продуманный интерфейс. Соответсвенно легко менять и сервер и хендлер...



Кстати
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.