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

С++ для начинающих

Войти
Регистрация
Восстановить пароль
 
 
Kukurudza
105 / 86 / 6
Регистрация: 29.08.2012
Сообщений: 539
#1

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

29.06.2014, 19:15. Просмотров 901. Ответов 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)
Similar
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
29.06.2014, 19:15
Здравствуйте! Я подобрал для вас темы с ответами на вопрос Сравнение производных классов (C++):

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

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

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

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

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

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

Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
Vladimir.
155 / 155 / 10
Регистрация: 24.11.2009
Сообщений: 375
29.06.2014, 19:24 #2
привести объект производного класса к базовому, сравнить приведенные объекты. dinamyc_cast вам в помощь
0
Kukurudza
105 / 86 / 6
Регистрация: 29.08.2012
Сообщений: 539
29.06.2014, 19:35  [ТС] #3
Хорошо, а если я хочу в будущем менять порядок следования объектов в контейнере?
Как я понял, вы предлагаете любой указатель приводить к указателю на базовый класс. Ок, привел. А как их потом сравнивать? Как понять что объект ЭТОГО типа "меньше" объекта вот ЭТОГО типа?
0
0x10
2463 / 1635 / 238
Регистрация: 24.11.2012
Сообщений: 4,026
29.06.2014, 19:37 #4
А можно чуть больше контекста? Почему было принято решение именно так делать?

PS Мне как-то приходилось поддерживать гетерогенную очередь с приоритетами... Отделался добавлением в каждый класс свойства "Приоритет".
1
Kukurudza
105 / 86 / 6
Регистрация: 29.08.2012
Сообщений: 539
29.06.2014, 19:43  [ТС] #5
0x10, ну собственно ваш способ это и есть мой первый метод, верно?
Цитата Сообщение от 0x10 Посмотреть сообщение
А можно чуть больше контекста? Почему было принято решение именно так делать?
Пока еще не принято никакого решения. Есть только задача. Я думаю как бы это решить получше. В целом задача как в первом посте. Есть иерархия классов. Может быть создан объект любого из классов. И хочется хранить объекты всех типов в одном контейнере (ну или в нескольких, главное чтобы для пользователя было прозрачно, пушнул указатель в контейнер, а как он там хранится, по барабану). При этом я, например, хочу выводить весь контейнер в файлик, в заданном МНОЮ порядке. апример, сначала все объекты класса S, затем A, затем B и так далее.
0
0x10
2463 / 1635 / 238
Регистрация: 24.11.2012
Сообщений: 4,026
29.06.2014, 19:59 #6
Цитата Сообщение от Kukurudza Посмотреть сообщение
ну собственно ваш способ это и есть мой первый метод, верно?
Я только не понял к чему в базовом классе какой-то enum.
0
Tulosba
:)
Эксперт С++
4395 / 3238 / 297
Регистрация: 19.02.2013
Сообщений: 9,045
29.06.2014, 20:07 #7
Цитата Сообщение от Kukurudza Посмотреть сообщение
хочу выводить весь контейнер в файлик, в заданном МНОЮ порядке
Отсортировать указатели с использованием своей функции сравнения и вывести. Лучше не стоит использовать std::set, если требуется какая-то своя сортировка только для целей вывода в определенном порядке.
1
Kukurudza
105 / 86 / 6
Регистрация: 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
Vladimir.
155 / 155 / 10
Регистрация: 24.11.2009
Сообщений: 375
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
0x10
2463 / 1635 / 238
Регистрация: 24.11.2012
Сообщений: 4,026
29.06.2014, 20:11 #10
Kukurudza, ну ок. Только я бы еще этот приоритет сделал бы static - к чему дублировать его в каждом объекте.
1
Kukurudza
105 / 86 / 6
Регистрация: 29.08.2012
Сообщений: 539
29.06.2014, 20:13  [ТС] #11
Vladimir., ваш метод это собственно такой же что и мой. только один из них более наглядный (в зависимости от опыта кодера )
0x10, ну да, разумеется. всем плюсанул. спасибо.
0
0x10
2463 / 1635 / 238
Регистрация: 24.11.2012
Сообщений: 4,026
29.06.2014, 20:13 #12
Vladimir., ну это хак, нецелевое использование возможностей языка. Нет гарантий, что при использовании другого компилятора будет полностью аналогично.
0
Voivoid
675 / 278 / 12
Регистрация: 31.03.2013
Сообщений: 1,339
29.06.2014, 20:21 #13
Лучший ответ Сообщение было отмечено автором темы, экспертом или модератором как ответ
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
Kukurudza
105 / 86 / 6
Регистрация: 29.08.2012
Сообщений: 539
29.06.2014, 20:22  [ТС] #14
Voivoid, пожалуй, вы лучший
0
0x10
2463 / 1635 / 238
Регистрация: 24.11.2012
Сообщений: 4,026
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
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
29.06.2014, 20:24
Привет! Вот еще темы с ответами:

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

Ошибка при создании двумерного массива из объектов производных классов - C++
Доброго времени суток. Для начала обрисую ситуацию. Мне нужно динамически создать двумерный массив из трех классов, для этого я создал...

Структура наследования базовых/производных классов: error LNK 1104 - C++
Может быть проблема, если я неправильно что-то записал в структуре наследования базовых/производных классов?

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


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

Или воспользуйтесь поиском по форуму:
Yandex
Объявления
29.06.2014, 20:24
Ответ Создать тему
Опции темы

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