Форум программистов, компьютерный форум, киберфорум
C++
Войти
Регистрация
Восстановить пароль
 
Рейтинг 4.86/7: Рейтинг темы: голосов - 7, средняя оценка - 4.86
0 / 0 / 0
Регистрация: 29.01.2010
Сообщений: 5
1

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

29.01.2010, 11:18. Показов 1279. Ответов 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.
0

Помощь в написании контрольных, курсовых и дипломных работ здесь.

Programming
Эксперт
94731 / 64177 / 26122
Регистрация: 12.04.2006
Сообщений: 116,782
29.01.2010, 11:18
Ответы с готовыми решениями:

Не меняет значение массива в родительском классе
Доброго времени суток! Помогите плиииз, а то бомбит. В общем, есть родительский класс First,...

Ошибка: нет члена в родительском классе
Добрый день! В коде ниже выбивает ошибку класс child не содержит члена g_out. ...

Можно ли переопределить функцию-член в унаследованном классе, не объявляя её виртуальной в родительском?
Предположим, есть абстрактный класс Worker. class Worker { protected: char *myName; ...

Создание объекта дочернего класса в родительском классе
Подскажите, может кто знает, как в предке сосдать экземпляр потомка? или как сделать копию this?...

9
Эксперт С++
1666 / 1038 / 174
Регистрация: 27.09.2009
Сообщений: 1,945
29.01.2010, 19:48 2
Писать в A конструктор и virtual void method1() = 0; можно. Разумеется, не только void, но и любой другой тип.
0
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. В итоге полиморфизм в таких деревьях не работает."
0
Эксперт С++
1666 / 1038 / 174
Регистрация: 27.09.2009
Сообщений: 1,945
01.02.2010, 18:53 4
Цитата Сообщение от Observat Посмотреть сообщение
В первом посте ключевая фраза: "Получается дерево, где корень имеет тип Bn, а все ветви и листья - тип A. В итоге полиморфизм в таких деревьях не работает."
Сначала надо разобраться, зачем нужно такое дерево, в котором полиморфизм не работает. Обычно при разборе таких ситуаций получается, что можно сделать так, чтобы и полиморфизм работал, и другие проблемы решались. Кроме того, в вышеприведённой фразе мне чудится какая-то путаница между типами объектов и типами указателей на них.
0
0 / 0 / 0
Регистрация: 29.01.2010
Сообщений: 5
02.02.2010, 10:05  [ТС] 5
Цитата Сообщение от Nick Alte Посмотреть сообщение
Сначала надо разобраться, зачем нужно такое дерево, в котором полиморфизм не работает.
У меня получается, а мне оно не надо, вот и спрашиваю как(!?)
можно сделать так, чтобы и полиморфизм работал, и другие проблемы решались
0
Эксперт С++
1666 / 1038 / 174
Регистрация: 27.09.2009
Сообщений: 1,945
02.02.2010, 18:42 6
Опиши проблему подробнее и обширнее. Зачем тебе надо такое дерево и из каких соображений оно именно такое? Чего ты хотел добиться?
0
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 из первого поста, хочу сделать рефакторинг.
0
Эксперт С++
1666 / 1038 / 174
Регистрация: 27.09.2009
Сообщений: 1,945
03.02.2010, 18:59 8
Во-первых, напиши в описании класса A
C++
1
2
    virtual void method1() =0;
    virtual int method2() =0;
и пользуйся на здоровье. Это раз. Во-вторых, если ты хочешь, чтобы потомки заполняли вектор такими же потомками, пусть они и делают это невозбранно в своём собственном конструкторе и ссыпают полученные указатели в тот вектор, что объявлен в A.
1
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
Это ничто иное как первый вариант первого поста, т.к. создавать без подключения к серверу не могу. Ведь неизвестно есть ли потомки, сколько их на уровне, сколько уровней?
0
Эксперт С++
1666 / 1038 / 174
Регистрация: 27.09.2009
Сообщений: 1,945
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);
    }
};
0
IT_Exp
Эксперт
87844 / 49110 / 22898
Регистрация: 17.06.2006
Сообщений: 92,604
04.02.2010, 18:51

Помощь в написании контрольных, курсовых и дипломных работ здесь.

Работа __construct() в родительском классе при наследовании
&lt;?php abstract class Controller { function __construct() { echo &quot;Call...

Сделать геттеры и сеттеры для наследников в родительском классе
Можно ли в родительском классе сделать геттеры и сеттеры для классов наследников если у них поля...

Как создать экземпляр внутреннего класса в родительском классе
Как создать экземпляр этого класса в статическом методе main. public class Parent { class...

Как можно посчитать среднее арифметическое в родительском классе
Допустим, есть класс товары(родительский): class Goods(object): def __init__(self, model,...

Изменить значение переменной в Родительском классе используя Потомственной класс
Всем привет. Я столкнулся с проблемой при выполнении одного задания. Хочу изменить значение...

Как добавить NotifyPropertyChanged если оно уже есть в родительском классе
Есть такая ObservableCollection: public class Profile : ObservableCollection&lt;SomeData&gt; ...


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

Или воспользуйтесь поиском по форуму:
10
Ответ Создать тему
Опции темы

КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2021, vBulletin Solutions, Inc.