Форум программистов, компьютерный форум CyberForum.ru

C++

Войти
Регистрация
Восстановить пароль
 
Observat
0 / 0 / 0
Регистрация: 29.01.2010
Сообщений: 5
#1

Создание дерева в родительском классе - C++

29.01.2010, 11:18. Просмотров 963. Ответов 9
Метки нет (Все метки)

Базовый класс используется для создания дерева. Потомки обрабатывают дерево по разному.
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
class A
{
public:
    A()
    {
        loadTree();
    }
    loadTree()
    {
        // заполнение данными c сервера
        // рекурсивно заполняется vector<A*>;
    }
//    method1() =0; // нельзя, т.к в loadTree() создается class A
private:
    vector<A*>;
};
 
class B1 : public A
{
public:
    B1() : A() {}
    method1()
    {
         // обработка данных
    }
//    method2(), ...
};
 
//class B2, B3 ...
Как изменить так, чтобы в loadTree() "рекурсивно заполнялся vector<Bn*>" и компилятор позволял в классе А написать method1() =0;
Т.е. пока получается дерево, где корень имеет тип Bn, а все ветви и листья - тип A. В итоге полиморфизм в таких деревьях не работает.
Я только 2 варианта вижу, оба не очень привлекательные:
1) в каждом Bn создавать метод loadTree();
2) в A создать метод method1(), который по какому нибудь признаку (можно ввести дополнительное поле для этого) через switch вызывает метод method1() соответствующего класса Bx.
После регистрации реклама в сообщениях будет скрыта и будут доступны все возможности форума.
Nick Alte
Эксперт С++
1603 / 995 / 118
Регистрация: 27.09.2009
Сообщений: 1,918
Завершенные тесты: 1
29.01.2010, 19:48     Создание дерева в родительском классе #2
Писать в A конструктор и virtual void method1() = 0; можно. Разумеется, не только void, но и любой другой тип.
Observat
0 / 0 / 0
Регистрация: 29.01.2010
Сообщений: 5
01.02.2010, 12:16  [ТС]     Создание дерева в родительском классе #3
Если отфильтровать и переформулировать вопрос, то требуется решить следующее:
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
class A
{
public:
    A()
    {
        if(b)
            p = new Bx();    // как указать какой из Bi тут вызывать?
                      // требуется такой же тип, как у родителя
                      // т.е. Bi->Bi, а не Bi->A или Bi->Bk
       else  p = NULL;
    }
    A* p;
};
 
class Bi : public A
{
public:
    Bi() :  A() {}
};
Можно ли передать в качестве параметра тип, а не значение(и не указатель на функцию)? Есть ли в С++ что-либо похожее на parent в Java и можно ли оттуда извлечь тип? Или мне организовать какой-либо шаблон и как конкретно? Может еще варианты есть?

В первом посте ключевая фраза: "Получается дерево, где корень имеет тип Bn, а все ветви и листья - тип A. В итоге полиморфизм в таких деревьях не работает."
Nick Alte
Эксперт С++
1603 / 995 / 118
Регистрация: 27.09.2009
Сообщений: 1,918
Завершенные тесты: 1
01.02.2010, 18:53     Создание дерева в родительском классе #4
Цитата Сообщение от Observat Посмотреть сообщение
В первом посте ключевая фраза: "Получается дерево, где корень имеет тип Bn, а все ветви и листья - тип A. В итоге полиморфизм в таких деревьях не работает."
Сначала надо разобраться, зачем нужно такое дерево, в котором полиморфизм не работает. Обычно при разборе таких ситуаций получается, что можно сделать так, чтобы и полиморфизм работал, и другие проблемы решались. Кроме того, в вышеприведённой фразе мне чудится какая-то путаница между типами объектов и типами указателей на них.
Observat
0 / 0 / 0
Регистрация: 29.01.2010
Сообщений: 5
02.02.2010, 10:05  [ТС]     Создание дерева в родительском классе #5
Цитата Сообщение от Nick Alte Посмотреть сообщение
Сначала надо разобраться, зачем нужно такое дерево, в котором полиморфизм не работает.
У меня получается, а мне оно не надо, вот и спрашиваю как(!?)
можно сделать так, чтобы и полиморфизм работал, и другие проблемы решались
Nick Alte
Эксперт С++
1603 / 995 / 118
Регистрация: 27.09.2009
Сообщений: 1,918
Завершенные тесты: 1
02.02.2010, 18:42     Создание дерева в родительском классе #6
Опиши проблему подробнее и обширнее. Зачем тебе надо такое дерево и из каких соображений оно именно такое? Чего ты хотел добиться?
Observat
0 / 0 / 0
Регистрация: 29.01.2010
Сообщений: 5
03.02.2010, 11:55  [ТС]     Создание дерева в родительском классе #7
Данные хранятся на сервере в виде дерева(типа XML, "файловая система, где каталог - полноценный файл с данными", LDAP). В разных ветвях встречаются разные вещи.
Мы знаем узел, начиная от которого идут нужные данные, но внутренняя структура нам неизвестна. Поэтому для загрузки данных используем некий обобщенный метод; создаем класс А.
Каждый узел содержит атрибуты. Некоторые из них мы не используем, некоторые только читаем, другие можем редактировать/удалять/создавать. Мы можем также скрывать некоторые узлы, которые нельзя использовать. Для разных вещей(загруженных деревьев) узлы, атрибуты и их чтение/редактирование/использование/контроль могут отличаться. Создаются классы B1-Bn. Некоторые методы (или их части) одинаковые или их можно сделать одинаковыми без потерь. Такие методы выносим в класс А.
Класс А не может самостоятельно обрабатывать данные, поэтому сделаем его абстрактным.
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
class A
{
public:
    A(char*/string/QString  str) {  loadTree(str);  }
    loadTree(char* root)
    {
        // заполнение данными c сервера
        // Рекурсивно заполняется vector<A*>;
//!    // но объектами (точнее указателями на созданные объекты)
//!    // не типа А, а типа Bx, который и вызвал конструктор класса А
    }
    void method1() =0;
    int method2() =0;
protected:
    ... // данные-атрибуты
    vector<A*>;
};
 
class B1 : public A
{
public:
    B1(char * root) : A(root) {}
    void method1() { ... }
    int method2() { ... }
protected:
// данных нет, они все в классе А
// могут быть только вспомогательные
};
 
void main()
{
  A* mas[2];
  mas[0] = new B1("qwerty");
  mas[1] = new B2("asd");
    ...
    mas[k]->method1();
}
Как сделать то , что отмечено "//!" ?

P.S. Неразвернутая по полочкам задача:
Клиент для LDAP-сервера для удобного добавления/редактирования DHCP, DNS, mail. Сейчас сделано по варианту 2 из первого поста, хочу сделать рефакторинг.
Nick Alte
Эксперт С++
1603 / 995 / 118
Регистрация: 27.09.2009
Сообщений: 1,918
Завершенные тесты: 1
03.02.2010, 18:59     Создание дерева в родительском классе #8
Во-первых, напиши в описании класса A
C++
1
2
    virtual void method1() =0;
    virtual int method2() =0;
и пользуйся на здоровье. Это раз. Во-вторых, если ты хочешь, чтобы потомки заполняли вектор такими же потомками, пусть они и делают это невозбранно в своём собственном конструкторе и ссыпают полученные указатели в тот вектор, что объявлен в A.
Observat
0 / 0 / 0
Регистрация: 29.01.2010
Сообщений: 5
04.02.2010, 15:58  [ТС]     Создание дерева в родительском классе #9
В класс А добавил абстрактную функцию newChild(). И в loadTree() строку "new A(...)" заменил на вызов этой функции. В классах Bi функция newChild() простая: { return new Bi(...); }
Все гениальное - просто! ))

Добавлено через 4 часа 33 минуты
Рано я радовался. Создаю второй объкт не доделав первый - примерно так компилятор ругается(ведь таблица виртуальных методов на этом этапе еще для класса А, не заменили ее еще на Вх).
Во-вторых, если ты хочешь, чтобы потомки заполняли вектор такими же потомками, пусть они и делают это невозбранно в своём собственном конструкторе и ссыпают полученные указатели в тот вектор, что объявлен в A
Это ничто иное как первый вариант первого поста, т.к. создавать без подключения к серверу не могу. Ведь неизвестно есть ли потомки, сколько их на уровне, сколько уровней?
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
04.02.2010, 18:51     Создание дерева в родительском классе
Еще ссылки по теме:

C++ Создание потока в классе
C++ Создание операторов в классе
Можно ли переопределить функцию-член в унаследованном классе, не объявляя её виртуальной в родительском? C++
C++ Создание класса в другом классе
Создание объекта в классе C++

Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
Nick Alte
Эксперт С++
1603 / 995 / 118
Регистрация: 27.09.2009
Сообщений: 1,918
Завершенные тесты: 1
04.02.2010, 18:51     Создание дерева в родительском классе #10
Объект класса Bx должен сам создавать объекты через new Bx(...), не вызывая при этом виртуальные методы. При этом указатели на полученные объекты заносятся в вектор, объявленный в A, но уже из конструктора Bx.
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
class A{
public:
    virtual void Method() = 0;
protected:
    vector<A*> children;
};
 
class B1: public A{
public:
    B1(const char* str)
    {
        for(int i=0; i<20; +i)
            children.push_back(new B1(str));
    }
};
Если все производные классы создают детей одинаково, можно воспользоваться шаблоном и сэкономить на писанине.
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
class A{
public:
    virtual void Method() = 0;
protected:
    vector<A*> children;
};
 
template<typename T>
void PopulateChildren(vector<A*> &children, const char* str)
{
    for(int i=0; i<20; ++i)
        children.push_back(new T(str));
}
 
class B1: public A{
public:
    B1(const char* str)
    {
        PopulateChildren<B1>(children, str);
    }
};
Yandex
Объявления
04.02.2010, 18:51     Создание дерева в родительском классе
Ответ Создать тему
Опции темы

Текущее время: 00:27. Часовой пояс GMT +3.
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2017, vBulletin Solutions, Inc.
Рейтинг@Mail.ru