Форум программистов, компьютерный форум, киберфорум
С++ для начинающих
Войти
Регистрация
Восстановить пароль
 
 
Рейтинг 4.77/13: Рейтинг темы: голосов - 13, средняя оценка - 4.77
105 / 86 / 13
Регистрация: 29.08.2012
Сообщений: 539
1

Сравнение производных классов

29.06.2014, 19:15. Просмотров 2670. Ответов 24
Метки нет (Все метки)

Друзья!
Пусть у меня есть базовый класс S. У него есть два наследника A и B. Как мне скидывать, например в set, указатели (шаредпэтэры например) на объекты классов A и B так, чтобы сначала шли объеты класса A, затем объекты класса B?
Понятно как сравнивать объекты класса только A или только B между собой, а как сравнивать объекты классов A и B между собой? Потенциально может быть и так что у A и B тоже будут наследники, например Aa, Ab, Ba и Bb. И тогда надо будет сравнивать все объекты между собой (S, A, B, Aa, Ab, Ba, Bb). Как такое делается?

Добавлено через 11 минут
У мея есть два варианта:
1. В класс S добавить enum, и в зависимости что за объект объявляем, выставлять IDшник этого объекта. таким образом у каждого обекта будет свой IDшник (возможно они будут повторяться, если например будет несколько объектов одного класса). Ну собственно сравнивать объекты по этому ID. Вроде норм, но кажется что этот ID это какой-то костыль
2. Сделать один супер контейнер, в котором указатели на контейнеры, каждый из которых хранит объекты только своего типа. Этот вариант мне нравится - не нужно хранить никакие ID и прочую "лишнюю" инфу, но вот как супер контейнер узнает объект какого типа ему передали и в какой контейнер его пушнуть? собственно это такой же вопрос как и в первом посте.
0
Лучшие ответы (1)
Programming
Эксперт
94731 / 64177 / 26122
Регистрация: 12.04.2006
Сообщений: 116,782
29.06.2014, 19:15
Ответы с готовыми решениями:

Наследование классов. Копирование производных классов
Здравствуйте всем, у меня такой вопрос: написал код #include "stdafx.h" class A //Создаем...

Использование базовых и производных классов
Не могу решить задачу с классами помогите с решением. Создать класс String – строка. Определить...

Файлы и объекты производных классов
Вопрос следующий: имеется два класса, базовый и производный. В файл бинарно записывается объект...

Массив объектов разных производных классов
Задача такая: базовый класс - фигура, производные классы - круг, треугольник и т.п. Пользователь...

24
375 / 226 / 79
Регистрация: 24.11.2009
Сообщений: 698
29.06.2014, 19:24 2
привести объект производного класса к базовому, сравнить приведенные объекты. dinamyc_cast вам в помощь
0
105 / 86 / 13
Регистрация: 29.08.2012
Сообщений: 539
29.06.2014, 19:35  [ТС] 3
Хорошо, а если я хочу в будущем менять порядок следования объектов в контейнере?
Как я понял, вы предлагаете любой указатель приводить к указателю на базовый класс. Ок, привел. А как их потом сравнивать? Как понять что объект ЭТОГО типа "меньше" объекта вот ЭТОГО типа?
0
3204 / 2015 / 346
Регистрация: 24.11.2012
Сообщений: 4,841
29.06.2014, 19:37 4
А можно чуть больше контекста? Почему было принято решение именно так делать?

PS Мне как-то приходилось поддерживать гетерогенную очередь с приоритетами... Отделался добавлением в каждый класс свойства "Приоритет".
1
105 / 86 / 13
Регистрация: 29.08.2012
Сообщений: 539
29.06.2014, 19:43  [ТС] 5
0x10, ну собственно ваш способ это и есть мой первый метод, верно?
Цитата Сообщение от 0x10 Посмотреть сообщение
А можно чуть больше контекста? Почему было принято решение именно так делать?
Пока еще не принято никакого решения. Есть только задача. Я думаю как бы это решить получше. В целом задача как в первом посте. Есть иерархия классов. Может быть создан объект любого из классов. И хочется хранить объекты всех типов в одном контейнере (ну или в нескольких, главное чтобы для пользователя было прозрачно, пушнул указатель в контейнер, а как он там хранится, по барабану). При этом я, например, хочу выводить весь контейнер в файлик, в заданном МНОЮ порядке. апример, сначала все объекты класса S, затем A, затем B и так далее.
0
3204 / 2015 / 346
Регистрация: 24.11.2012
Сообщений: 4,841
29.06.2014, 19:59 6
Цитата Сообщение от Kukurudza Посмотреть сообщение
ну собственно ваш способ это и есть мой первый метод, верно?
Я только не понял к чему в базовом классе какой-то enum.
0
:)
Эксперт С++
4763 / 3257 / 497
Регистрация: 19.02.2013
Сообщений: 9,046
29.06.2014, 20:07 7
Цитата Сообщение от Kukurudza Посмотреть сообщение
хочу выводить весь контейнер в файлик, в заданном МНОЮ порядке
Отсортировать указатели с использованием своей функции сравнения и вывести. Лучше не стоит использовать std::set, если требуется какая-то своя сортировка только для целей вывода в определенном порядке.
1
105 / 86 / 13
Регистрация: 29.08.2012
Сообщений: 539
29.06.2014, 20:08  [ТС] 8
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
enum enm {
    S_ENM = 0,
    A_ENM = 1,
};
 
class S {
    const enm ID_;
 
public:
    explicit S() : ID_(S_ENM) {
    }
 
    explicit S(const enm ID) : ID_(ID) {
    }
 
    //  компаратор по ID_
};
 
class A : public S {
public:
    explicit A() : S(A_ENM) {
    }
};
при добавлении нового наследника, просто добавляем его ID в enum
че нить такое?
0
375 / 226 / 79
Регистрация: 24.11.2009
Сообщений: 698
29.06.2014, 20:09 9
Цитата Сообщение от Kukurudza Посмотреть сообщение
При этом я, например, хочу выводить весь контейнер в файлик, в заданном МНОЮ порядке. апример, сначала все объекты класса S, затем A, затем B и так далее.
простите, не правильно вас понял вначале.
Посмотрите:
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
#include <iostream>
#include <typeinfo>
#include <memory>
 
class B {
public:
   virtual void foo() {}
};
 
class Ch1 : public B {};
class Ch2 : public B {};
class Ch3 : public Ch1 {};
 
using namespace std;
int main() {
   shared_ptr<B> ptr1(new B);
   shared_ptr<B> ptr2(new Ch1);
   shared_ptr<B> ptr3(new Ch2);
   shared_ptr<B> ptr4(new Ch3);
   
   cout << typeid( *ptr1 ).name() << endl;   
   cout << typeid( *ptr2 ).name() << endl;   
   cout << typeid( *ptr3 ).name() << endl;   
   cout << typeid( *ptr4 ).name() << endl;   
   cout<< typeid( *ptr4 ).before(typeid( *ptr1))<<endl;
   cout<< typeid( *ptr2 ).before(typeid( *ptr4))<<endl;   
}
вывод:
Код
1B
3Ch1
3Ch2
3Ch3
0
1
1
3204 / 2015 / 346
Регистрация: 24.11.2012
Сообщений: 4,841
29.06.2014, 20:11 10
Kukurudza, ну ок. Только я бы еще этот приоритет сделал бы static - к чему дублировать его в каждом объекте.
1
105 / 86 / 13
Регистрация: 29.08.2012
Сообщений: 539
29.06.2014, 20:13  [ТС] 11
Vladimir., ваш метод это собственно такой же что и мой. только один из них более наглядный (в зависимости от опыта кодера )
0x10, ну да, разумеется. всем плюсанул. спасибо.
0
3204 / 2015 / 346
Регистрация: 24.11.2012
Сообщений: 4,841
29.06.2014, 20:13 12
Vladimir., ну это хак, нецелевое использование возможностей языка. Нет гарантий, что при использовании другого компилятора будет полностью аналогично.
0
710 / 282 / 16
Регистрация: 31.03.2013
Сообщений: 1,340
29.06.2014, 20:21 13
Лучший ответ Сообщение было отмечено Kukurudza как решение

Решение

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
class S {
public:
  virtual int priority() const {
    return 1;
  }
 
  struct comparer {
    bool operator()( const S* s1, const S* s2 ) const {
      return s1->priority() < s2->priority();
    }
  };
};
 
class B : public S {
public:
  virtual int priority() const {
    return 2;
  }
};
 
class C : public S {
public:
  virtual int priority() const {
    return 3;
  }
};
 
int main() {
  std::set<S*, S::comparer> objs;
  objs.insert( new B );
 
  return 0;
}
0
105 / 86 / 13
Регистрация: 29.08.2012
Сообщений: 539
29.06.2014, 20:22  [ТС] 14
Voivoid, пожалуй, вы лучший
0
3204 / 2015 / 346
Регистрация: 24.11.2012
Сообщений: 4,841
29.06.2014, 20:24 15
Voivoid, у меня когда-то примерно так и было реализовано) А потом совесть замучила за то, что везде дублируется функция, отличающаяся не поведением, а только данными.
В итоге получилось что-то такое:
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
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
#include <algorithm>
#include <iostream>
#include <memory>
#include <string>
#include <vector>
 
class BasePriority {
public:
    virtual int GetPriority() const = 0;
    virtual std::string Name() const = 0;
};
 
template <int p>
class Priority : public BasePriority {
public:
    int GetPriority() const override { return priority_; }
private:
    static const int priority_ = p;
};
 
class A : public Priority<2> {
public:
    std::string Name() const override {
        return "class A";
    }
};
 
class B : public Priority<1> {
public:
    std::string Name() const override {
        return "class B";
    }
};
 
typedef std::shared_ptr<BasePriority> BasePriorityPtr;
typedef std::vector<BasePriorityPtr> BasePtrContainer;
 
int main() {
    struct PriorityComparator {
        bool operator()(const BasePriorityPtr& lhs,
                const BasePriorityPtr& rhs) const {
            return lhs->GetPriority() < rhs->GetPriority();
        }
    };
        
    BasePtrContainer container {
        std::make_shared<B>(),
        std::make_shared<A>(),
        std::make_shared<B>(),
        std::make_shared<B>()
    };
    
    std::sort(container.begin(), container.end(), PriorityComparator());
    
    for (const auto& item : container) {
        std::cout << item->Name() << std::endl;
    }
    
    return 0;
}
Иерархия жирнее, но дублирования уже нет.
1
105 / 86 / 13
Регистрация: 29.08.2012
Сообщений: 539
29.06.2014, 20:27  [ТС] 16
0x10, хитрец
0
:)
Эксперт С++
4763 / 3257 / 497
Регистрация: 19.02.2013
Сообщений: 9,046
29.06.2014, 20:29 17

Не по теме:

0x10, а чего компаратор не ввиде лямбды, раз уж C++11? :)

Цитата Сообщение от 0x10 Посмотреть сообщение
А потом совесть замучила за то, что везде дублируется функция, отличающаяся не поведением, а только данными.
C++
1
std::string Name() const override { return "class A"; }
0
105 / 86 / 13
Регистрация: 29.08.2012
Сообщений: 539
29.06.2014, 20:31  [ТС] 18
Tulosba, а что не так?
0
3204 / 2015 / 346
Регистрация: 24.11.2012
Сообщений: 4,841
29.06.2014, 20:31 19
Tulosba, все можно - главное, идея показана)
0
:)
Эксперт С++
4763 / 3257 / 497
Регистрация: 19.02.2013
Сообщений: 9,046
29.06.2014, 20:33 20
Цитата Сообщение от Kukurudza Посмотреть сообщение
а что не так?
Цитата Сообщение от 0x10 Посмотреть сообщение
C++
1
std::string Name() const override { return "class A"; }
Цитата Сообщение от Voivoid Посмотреть сообщение
C++
1
virtual int priority() const { return 2; }
Подход одинаковый (но для разных целей).
0
IT_Exp
Эксперт
87844 / 49110 / 22898
Регистрация: 17.06.2006
Сообщений: 92,604
29.06.2014, 20:33

Заказываю контрольные, курсовые, дипломные и любые другие студенческие работы здесь.

Функция создающая объекты производных классов
Функция получает входной параметр - целое число. Если оно равно 0, создается новый объект -...

Множественное наследование. Построение производных классов
Необходимо построить иерархию классов согласно схемы наследования. Каждый класс должен содержать...

Конструктор по умолчанию для производных классов
Допустим, имеется код: class abstr_emp { private: string fname; // abstr_emp's first...

Конструктор копирования производных классов: для чего это нужно?
Доброго времени суток! #ifndef EMP_H #define EMP_H #include &lt;iostream&gt; #include &lt;string&gt; ...


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

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

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