Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > C/C++: Для новичков > наследование и двусвязные списки


Автор: SlowCheetah 26.10.2008, 10:42
подкиньте идею создания класса списка для двух других классов(базового и производного), т.е для этих классов должен быть составлен класс - список, в котором есть все данные(next, prev) и функции работы со списком, причем список можно применять как к базовому, так и к производному классам по отдельности. класс-список для одного другого я составил, а потом возникли кое-какие вопросы

пример:
// два класса не списка

class base { /* ... */ };
class derived { /* ... */ }

и для них должен быть какой-нибудь List
class List { /* ... */ };

// вопрос - как лучше сделать?
// сделать производным List от base
// class List : public base { /* ... */ }
// а потом derived от List
//class derived : public List { /* ... */ }
// или же сначала derived от base
// а потом list от derived ???

// или можно как-то лучше сделать ???

Автор: mes 26.10.2008, 11:16
не до конца понял вопрос.

std::list<> чем не подходит ?

Автор: SlowCheetah 26.10.2008, 13:48
если б можно было использовать std::list, я б использовал конечно же, но в данной конкретной задаче этого делать не нужно

Добавлено через 2 минуты и 58 секунд
в общем нужно написать для двух классов(базового и производного) класс-список, который мог работать как с одним, так и с другим, так и с обоими сразу, вопрос в том, как лучше эту конструкцию организовать?  

Автор: Shooroop 26.10.2008, 21:36
обратите внимание на полиморфизм и "указатель на void"
насколько я понял задачу то это должно помочь 
Код

#include <iostream>
using namespace std;
class base
{
    virtual void out()=NULL;
};
class cl1 :public base
{
public:
    void out()
    {cout<<"cl1"<<endl;}
};
class cl2 :public base
{
public:
    void out()
    {cout<<"cl2"<<endl;};
};
struct node
{
    base *data;
    node *next;
};
class list
{
protected:
    node *top;
    void add_node(node *_add_node)
    {
        if(top==NULL)
        {
            top=_add_node;
        }
        else
        {
            node *temp=top;
            while(temp->next!=NULL)
                temp=temp->next;
            temp->next=_add_node;
        }
    }
public:
    list()
    {top=NULL;}
    void add(cl1 *_add)
    {
        node *temp=new node;
        temp->data=reinterpret_cast<base *>(_add);
        temp->next=NULL;
        add_node(temp);
    }
    void add(cl2 *_add)
    {
        node *temp=new node;
        temp->data=reinterpret_cast<base *>(_add);
        temp->next=NULL;
        add_node(temp);
    }
    void out()
    {
        node *temp=top;
        while(temp!=NULL)
        {
            if(cl1 *c1=dynamic_cast<cl1 *>(temp->data)) c1->out();
            else if(cl2 *c2=dynamic_cast<cl2 *>(temp->data)) c2->out();
            temp=temp->next;
        }
    }
};
void main()
{
    list *ls=new list();
    ls->add(new cl2());
    ls->add(new cl1());
    ls->out();

    cin.get();
}

Автор: SlowCheetah 26.10.2008, 22:38
ок

Автор: J0ker 27.10.2008, 03:03
Цитата(Shooroop @  26.10.2008,  21:36 Найти цитируемый пост)
и "указатель на void"

а вот этого делать не надо

Автор: Rickert 27.10.2008, 04:23
Shooroop, я бы сделал класс шаблон и третий класс, который бы являлся наследником первых двух. И использовал тот, который нужен.

Автор: J0ker 27.10.2008, 05:35
Цитата(Rickert @ 27.10.2008,  04:23)
Shooroop, я бы сделал класс шаблон и третий класс, который бы являлся наследником первых двух. И использовал тот, который нужен.

ээээ
чиста академический интерес - каких "первых двух"?
и при чем тут шаблон
и зачем усложнять себе жизнь множественным наследованием?

Добавлено через 3 минуты и 35 секунд
Цитата(Shooroop @  26.10.2008,  21:36 Найти цитируемый пост)

Код

if(cl1 *c1=dynamic_cast<cl1 *>(temp->data)) c1->out();
    else if(cl2 *c2=dynamic_cast<cl2 *>(temp->data)) c2->out();



оппа, вот это ж*па  smile 
пардон, не удержался - рифма понравилась  smile 
а сразу temp->data->out() не судьба?

Добавлено через 11 минут и 14 секунд


Цитата(Shooroop @  26.10.2008,  21:36 Найти цитируемый пост)

Код

void add(cl1 *_add)

void add(cl2 *_add)


а это что?
да у вас тут прям Клондайк

void add(base *b)
!!!!

Добавлено через 12 минут и 3 секунды
вот научи кастать - они себе и лоб расшибут  smile 

Автор: Rickert 27.10.2008, 06:26
Цитата(J0ker @  27.10.2008,  05:35 Найти цитируемый пост)
ээээ
чиста академический интерес - каких "первых двух"?
и при чем тут шаблон
и зачем усложнять себе жизнь множественным наследованием?

Два класса, которые даны человеку изначально.
Шаблон при том, что на нём основывать двусвязанный список.

Автор: J0ker 27.10.2008, 06:43
Цитата(Rickert @ 27.10.2008,  06:26)
Цитата(J0ker @  27.10.2008,  05:35 Найти цитируемый пост)
ээээ
чиста академический интерес - каких "первых двух"?
и при чем тут шаблон
и зачем усложнять себе жизнь множественным наследованием?

Два класса, которые даны человеку изначально.
Шаблон при том, что на нём основывать двусвязанный список.

т.е. вы предлагаете древо наследования расположить вверх корнём?  smile 
а зачем?

Автор: Rickert 27.10.2008, 07:57
J0ker при чём тут расположение дерева корнём вверх?

Автор: J0ker 27.10.2008, 17:39
Цитата(Rickert @ 27.10.2008,  07:57)
J0ker при чём тут расположение дерева корнём вверх?

ну в данном случае предложение использовать множественное наследование мне видится исключительно в таком свете

Автор: mes 27.10.2008, 18:29
чего то я не догоню  какое отношение имеет в данном задании наследник к списку (помимо того, что уже обусловенно полиморфизмом) ?

Автор: baldina 27.10.2008, 20:06
важный вопрос, является ли derived : public base или derived : private base.
в первом случае реализуется List, хранящий указатели на base и c равным успехом применяемый к объектам любого из этих классов, вместе или по отдельности.
если наследование закрытое, то требуется другая реализация List: либо при помощи шаблона (что имхо лучше), либо List, хранящий void* + приведения типа при использовании элементов списка.

вопросов, конечно, больше, например, отличается ли в случае derived : public base только полиморфным поведением, т.е. потребуется ли в каких-то случаях приведение типа. все эти вопросы в общем виде решаются, если написать упрощенный аналог std::list<>

т.к. SlowCheetah использовать std::list<> не хочет, скорее всего от него требуется List, хранящий указатели на base. что-то вроде

Код

class List {
public:
  void add (base*);
  base* first();
  base* last();
  base* next();
  base* prev();
};


SlowCheetah, class List не может быть ни базовым, ни производным от base либо derived ибо не связан с ними ни отношением "является", ни "реализован посредством". Он хранит объекты этого типа, он - контейнер, ему по большому счету все-равно что эти классы из себя представляют.

Автор: Shooroop 28.10.2008, 18:41
Цитата(J0ker @ 27.10.2008,  01:03)
Цитата(Shooroop @  26.10.2008,  21:36 Найти цитируемый пост)
и "указатель на void"

а вот этого делать не надо

почему??

Добавлено через 8 минут и 48 секунд
Цитата(J0ker @ 27.10.2008,  03:35)
Цитата(Rickert @ 27.10.2008,  04:23)
Shooroop, я бы сделал класс шаблон и третий класс, который бы являлся наследником первых двух. И использовал тот, который нужен.

ээээ
чиста академический интерес - каких "первых двух"?
и при чем тут шаблон
и зачем усложнять себе жизнь множественным наследованием?

Добавлено @ 05:39
Цитата(Shooroop @  26.10.2008,  21:36 Найти цитируемый пост)

Код

if(cl1 *c1=dynamic_cast<cl1 *>(temp->data)) c1->out();
    else if(cl2 *c2=dynamic_cast<cl2 *>(temp->data)) c2->out();



оппа, вот это ж*па  smile 
пардон, не удержался - рифма понравилась  smile 
а сразу temp->data->out() не судьба?

Добавлено @ 05:46


Цитата(Shooroop @  26.10.2008,  21:36 Найти цитируемый пост)

Код

void add(cl1 *_add)

void add(cl2 *_add)


а это что?
да у вас тут прям Клондайк

void add(base *b)
!!!!

Добавлено @ 05:47
вот научи кастать - они себе и лоб расшибут  smile

Согласен множественное наследование я особо бы не использовал

обратите внимание каждый класс заносится в список разными методами. Возможно классы надо будет по разному интерпретировать и обрабатывать. Тоже и при выводе списка. Смысл такой: сначала класс идентифицируется, а потом выполняются функции специфичные для него.

Автор: J0ker 28.10.2008, 19:53
Цитата(Shooroop @  28.10.2008,  18:41 Найти цитируемый пост)
Цитата(J0ker @ 27.10.2008,  01:03)
Цитата(Shooroop @  26.10.2008,  21:36 Найти цитируемый пост)
и "указатель на void"

а вот этого делать не надо

почему??

что-бы не компрометировать систему безопасности типов C++ - вам-же потом и отольется

Цитата(Shooroop @  28.10.2008,  18:41 Найти цитируемый пост)
обратите внимание каждый класс заносится в список разными методами. Возможно классы надо будет по разному интерпретировать и обрабатывать. Тоже и при выводе списка. Смысл такой: сначала класс идентифицируется, а потом выполняются функции специфичные для него. 

данный смысл реализован встренным в язык механизмом полиморфизма. Занесение разными методами бессмысленно вообще.


Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)