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

Сравнение наследников - C++

Восстановить пароль Регистрация
 
togramago
9 / 9 / 0
Регистрация: 03.11.2009
Сообщений: 39
24.01.2010, 19:42     Сравнение наследников #1
Здравствуйте!
А как можно сравнить два наследника, если есть только указатели на базовый класс?
У наследников определены ==, !=, >=, <=, >, <, которые в базе также определены, но виртуальны.
Наследники загнаны в
C++
1
vector<Base *> ds;
Есть ли какой-то нормальный способ?
и если есть - то какой?
После регистрации реклама в сообщениях будет скрыта и будут доступны все возможности форума.
SerЁga
32 / 32 / 4
Регистрация: 18.08.2009
Сообщений: 93
24.01.2010, 20:29     Сравнение наследников #2
C++
1
2
3
4
vector<int> vc; 
vc.push_back(3);
vc.push_back(5);    
if(vc[0]!=vc[1]) cout<<"aaa";
В твоем случае vc[x] вернет Base* разадресуй и сравнивай
zim22
depict1
 Аватар для zim22
276 / 141 / 2
Регистрация: 11.07.2009
Сообщений: 606
24.01.2010, 20:41     Сравнение наследников #3
Цитата Сообщение от SerЁga Посмотреть сообщение
В твоем случае vc[x] вернет Base* разадресуй и сравнивай
c чего ты взял, что Base получится разыменовать? вдруг это абстрактный класс.
***
я пока-что так придумал, но мне моё решение не нравится.
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
struct Base {
  virtual bool equal(Base*) = 0;  
};
 
struct Derived : Base {
  Derived(int data) : data_(data) { }
  
  virtual bool equal(Base *base) {
    return Derived::operator==(static_cast<const Derived&>(*base));
  }
 
  bool operator==(const Derived &rhs) {
    return data_ == rhs.data_;
  }
 
private:
  int data_;
};
 
int main()
{
  Base *ptr1 = new Derived(10);
  Base *ptr2 = new Derived(20);
 
  ptr1->equal(ptr2);  
}
togramago
9 / 9 / 0
Регистрация: 03.11.2009
Сообщений: 39
24.01.2010, 21:12  [ТС]     Сравнение наследников #4
Спасибо!

Но дело в том что у меня два наследника от одной базы (1)
и да, база действительно абстрактная. (2)

вот, собсно, код:
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
class Ware
{
    char * name;
    double price;
public:
//....
    virtual double getAdd() const = 0; 
    
    const Ware & getWare() const;
 
    Ware & operator=(const Ware & w);
    
    virtual void show() const;
    virtual void show(std::ostream & os) const = 0
 
    virtual bool operator==(const Ware & w);
    virtual bool operator!=(const Ware & w);
    virtual bool operator>(const Ware & w);
    virtual bool operator<(const Ware & w);
    virtual bool operator>=(const Ware & w);
    virtual bool operator<=(const Ware & w);
};
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
class Item: public Ware
{
 
    Company producer;
    int a, b, c;
public:
    //...
    const Item & getItem() const;
 
    double getAdd() const;
 
    Item & operator=(const Item & i);
    void show() const;
    void show(std::ostream & os) const;
 
    bool operator==(const Item & i);
    bool operator!=(const Item & i);
    bool operator>=(const Item & i);
    bool operator<=(const Item & i);
    bool operator>(const Item & i);
    bool operator<(const Item & i);
};
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
class Service: public Ware
{
    Performer performer;
    int complicacy;
public:
    //...
 
    Service & operator=(const Service & s);
 
    const Service & getService() const;
 
    double getAdd() const;
    void show() const;
    void show(std::ostream & os) const;
    
    bool operator==(const Service & i);
    bool operator!=(const Service & i);
    bool operator>=(const Service & i);
    bool operator<=(const Service & i);
    bool operator>(const Service & i);
    bool operator<(const Service & i);
 
};
у меня операторы сравнения перегружены, но при работе с указателями это бессмысленно (сравнивает адреса), если разыменовывать, то сравнивает сами Ware - а они ведь могут быть одинаковыми для Item и Service.

В процессе исканий я думала использовать typeid вот так

C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
bool cmp(Ware * w1, Ware * w2)
{
    if (typeid(*w1) == typeid(*w2))
    {
        char * s = strdup(typeid(*w1).name());
        if (s[0] == 'S')
        {
            Service s1(w1->getName(), w1->getPrice(), w1->getPerformer(), w1->getComplicacy());
            Service s2(w2->getName(), w2->getPrice(), w2->getPerformer(), w2->getComplicacy());
            return s1 == s2;
        }
        else
        {
            Item i1(w1->getName(), w1->getPrice(), w1->getA(), w1->getB(), w1->getC());
            Item i2(w2->getName(), w2->getPrice(), w2->getA(), w2->getB(), w2->getC());
            return i1 == i2;
        }
    }
    return false;
}
но у вид у этой функции мне не нравится, какой-то он странный
+ компилятор говорит что у Ware * нету функций getPerformer() и тд
zim22
depict1
 Аватар для zim22
276 / 141 / 2
Регистрация: 11.07.2009
Сообщений: 606
24.01.2010, 21:37     Сравнение наследников #5
Цитата Сообщение от togramago Посмотреть сообщение
vector<Base *> ds;
у тебя в векторе два вида классов хранится(Service, Item)?
Каждый класс должен сравниваться только со своим классом? Или Service может с Item сравниваться?
Зачем ты вообще определила все виды операторов отношения(>,<,>=,...)?
***
вот я ещё один вид решения реализовал. но я думал, что у тебя только один подкласс. поэтому и приводил к нему явно.
это паттерн "Стратегия".

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
struct Base { 
};
 
struct Derived : Base {
  friend struct EqualStrategy;
  friend struct NotEqualStrategy;
 
  Derived(int data) : data_(data) { }  
private:
  int data_;
};
 
struct Strategy {
  virtual bool compare(Base *lhs, Base *rhs) = 0;
};
 
struct EqualStrategy : Strategy {
  virtual bool compare(Base *lhs, Base *rhs) {
    return ((Derived*)lhs)->data_ == ((Derived*)rhs)->data_;
  }
};
 
struct NotEqualStrategy : Strategy {
  virtual bool compare(Base *lhs, Base *rhs) {
    return ((Derived*)lhs)->data_ != ((Derived*)rhs)->data_;
  }
};
 
struct Context {
private:
  Strategy *strategy_;
public:
  Context() { }
  
  bool compare(const char *operation, Base *b1, Base *b2) {
    
    if (strcmp(operation, "==") == 0) {
      strategy_ = new EqualStrategy;
    } else if (strcmp(operation, "!=") == 0) {
      strategy_ = new NotEqualStrategy;
    }
    return strategy_->compare(b1, b2);
  }
};
 
int main()
{
  Base *ptr1 = new Derived(10);
  Base *ptr2 = new Derived(20);
 
  Context c;
  bool res = c.compare("!=", ptr1, ptr2);
  
}
Добавлено через 18 минут
двойную диспетчеризацию можно применить для того, чтобы выяснить оба типа объекта, переданные через указатель на их базовые классы. вобщем togramago тебя ждёт много веселья

http://bytes.com/topic/c/answers/168...tor#post653324
togramago
9 / 9 / 0
Регистрация: 03.11.2009
Сообщений: 39
24.01.2010, 22:29  [ТС]     Сравнение наследников #6
Цитата Сообщение от zim22 Посмотреть сообщение
у тебя в векторе два вида классов хранится(Service, Item)?
-да

Цитата Сообщение от zim22 Посмотреть сообщение
Каждый класс должен сравниваться только со своим классом? Или Service может с Item сравниваться?
каждый с подобным. Service может с Item, но они неравны никак.

Цитата Сообщение от zim22 Посмотреть сообщение
Зачем ты вообще определила все виды операторов отношения(>,<,>=,...)?
- надобно операции поперегружать (курсовая) - что смогла, то перегрузила, называется (

Цитата Сообщение от zim22 Посмотреть сообщение
двойную диспетчеризацию можно применить для того, чтобы выяснить оба типа объекта, переданные через указатель на их базовые классы. вобщем togramago тебя ждёт много веселья
да, целая ночь веселья у меня впереди
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
25.01.2010, 11:34     Сравнение наследников
Еще ссылки по теме:

Наследование. Неправильная работа одного из классов наследников C++
Запись в базовый класс информации из наследников C++
C++ Организация вызова всех наследников

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

Или воспользуйтесь поиском по форуму:
zim22
depict1
 Аватар для zim22
276 / 141 / 2
Регистрация: 11.07.2009
Сообщений: 606
25.01.2010, 11:34     Сравнение наследников #7
вот решение? твоей проблемы, используя двойную диспетчеризацию.
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
class Derived1;
class Derived2;
 
class Base {
public:
  virtual bool operator==(Base*) = 0;
  virtual bool operator==(Derived1*) = 0;
  virtual bool operator==(Derived2*) = 0;
 
  virtual ~Base() { }
};
 
class Derived1 : public Base {
  friend class Derived2;
  int v_;
public:
  Derived1(int v) : v_(v) { }
 
  virtual bool operator==(Base *base) {
    return base->operator==(this);
  }
  virtual bool operator==(Derived1 *d1) { 
    return v_ == d1->v_; 
  }
  virtual bool operator==(Derived2 *d2) { 
    return d2->x_ + d2->y_ == v_;
  }
};
 
class Derived2 : public Base {
  friend class Derived1;
  int x_, y_;
public:
  Derived2(int x, int y) : x_(x), y_(y) { }
 
  virtual bool operator==(Base *base) {
    return base->operator==(this);
  }
  virtual bool operator==(Derived1 *d1) { 
    return x_ + y_ == d1->v_; 
  }
  virtual bool operator==(Derived2 *d2) { 
    return x_ + y_ == d2->x_ + d2->y_; 
  }
};
 
int _tmain(int argc, _TCHAR* argv[])
{
  Base *d1 = new Derived1(70);
  Base *d2 = new Derived2(30, 40);
  
  bool result = d1->operator==(d2);
 
  return 0;
}
Добавлено через 1 минуту
***
ну а вот более простой пример на саму double dispatch
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
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
// 619.cpp : Defines the entry point for the console application.
//
 
#include "stdafx.h"
#include <iostream>
using namespace std;
 
class Triangle;
class Square;
class Circle;
 
class Shape {
public:
  virtual void intersection(Shape*) = 0;
  virtual void intersection(Triangle*) = 0;
  virtual void intersection(Square*) = 0;
  virtual void intersection(Circle*) = 0;
 
  virtual ~Shape() { }
};
 
class Circle : public Shape {
public:
  virtual void intersection(Shape *shape) {    
    shape->intersection(this);
  }
  virtual void intersection(Triangle *triangle) { 
    cout << "Triangle with Circle" << endl;
  }
  virtual void intersection(Square *square) { 
    cout << "Square with Circle" << endl;
  }
  virtual void intersection(Circle *circle) { 
    cout << "Circle with Circle" << endl;
  }
};
 
class Triangle : public Shape {
public:
  virtual void intersection(Shape *shape) {    
    shape->intersection(this);
  }
  virtual void intersection(Triangle *triangle) {     
    cout << "Triangle with Triangle" << endl;
  }
  virtual void intersection(Square *square) { 
    cout << "Square with Triangle" << endl;
  }
  virtual void intersection(Circle *circle) { 
    cout << "Circle with Triangle" << endl;
  }
};
 
class Square : public Shape {
public:
  virtual void intersection(Shape *shape) {    
    shape->intersection(this);
  }
  virtual void intersection(Triangle *triangle) { 
    cout << "Triangle with Square" << endl;
  }
  virtual void intersection(Square *square) { 
    cout << "Square with Square" << endl;
  }
  virtual void intersection(Circle *circle) { 
    cout << "Circle with Square" << endl;
  }
};
 
void intersection(Shape *lhs, Shape *rhs) {
  lhs->intersection(rhs);
}
int _tmain(int argc, _TCHAR* argv[])
{
  Circle c;
  Square s;
  Triangle t;  
  intersection(&c, &t);
  return 0;
}
Yandex
Объявления
25.01.2010, 11:34     Сравнение наследников
Ответ Создать тему
Опции темы

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