Здравствуйте, Аноним, Вы писали:
А>Здрасьте, народ!
А>Наткнулся на такое: А>1. Есть виртуальный базовый класс: А. А>2. Есть наследнкики класса А: B,C,D... (любых видов наследования в том числе и ромбового). А>3. Есть шаблонный класс реализующий тип "множество". T А>4. В программе используются соотвественно указатели на базоывй класс A: T<A*> set1;
А>Нужно реализовать в шаблонном классе Т проверку того, что бы небыло одинаковых элементов в множестве.
А>Делаю так: объявил виртуальный оператор == в базовом классе как чистый. А>Ну а далее тоже переопределил для наследников. Потом столкнулся с тем, что базовый указатель не имеет доступ к методам наследников, чтобы сравнить значения на совпадения. Пробовал dynamic_cast тоже не срабатывает.. А>Как такое решать?
Если объекты разных типов не могут быть равны друг другу, то можно, например, так:
class A {
public:
bool operator == ( const A& other ) const { return typeid( *this ) == typeid( other ) && callIsEqu( other ); }
protected:
virtual bool callIsEqu( const A& other ) { return isEqu( other ); }
bool isEqu( const A& ); // реализуешь, как надо
};
class B : A {
protected:
virtual bool callIsEqu( const A& other ) { return isEqu( dynamic_cast<const B&>( other ) ); }
bool isEqu( const B& ); // реализуешь, как надо, можно юзать A::isEqu
};
class C : A {
protected:
virtual bool callIsEqu( const A& other ) { return isEqu( dynamic_cast<const C&>( other ) ); }
bool isEqu( const C& ); // реализуешь, как надо, можно юзать A::isEqu
};
class D : B, C {
protected:
virtual bool callIsEqu( const A& other ) { return isEqu( dynamic_cast<const D&>( other ) ); }
bool isEqu( const D& )
{
if( !B::isEqu( other ) || !C::isEqu( other ) )
return false;
return"реализуешь, как надо";
}
};
А>то для случая T<A*> set; код будет верен а для случая T<int> ошибочно. А>Кто подскажет как реализовать более грамотно.
Если ты не являешься рабом VC 6.0, то следует воспользоваться механизмом частичных специализаций.
Если же являешься, то надо воспользоваться шаблонами перегруженных функций.
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Это тебе над множественную диспетчеризацию по двум параметрам
делать с помощью шаблона проектирования Visitor.
Posted via RSDN NNTP Server 2.1 beta
virtual operator==
От:
Аноним
Дата:
13.11.09 17:51
Оценка:
Здрасьте, народ!
Наткнулся на такое:
1. Есть виртуальный базовый класс: А.
2. Есть наследнкики класса А: B,C,D... (любых видов наследования в том числе и ромбового).
3. Есть шаблонный класс реализующий тип "множество". T
4. В программе используются соотвественно указатели на базоывй класс A: T<A*> set1;
Нужно реализовать в шаблонном классе Т проверку того, что бы небыло одинаковых элементов в множестве.
Делаю так: объявил виртуальный оператор == в базовом классе как чистый.
Ну а далее тоже переопределил для наследников. Потом столкнулся с тем, что базовый указатель не имеет доступ к методам наследников, чтобы сравнить значения на совпадения. Пробовал dynamic_cast тоже не срабатывает..
Как такое решать?
Кроме того непонятно совершенно как решать такую задачу на проверку совместимости в шаблоне: мы знаем что типы могут быть указателями или переменные.
так что если я напишу:
bool T<t>::add(t element)
{
...
if(*s==*element)
return false; //элемент уже имеется в множестве
...
return true; //элемент успешно вставлен в множество
}
то для случая T<A*> set; код будет верен а для случая T<int> ошибочно.
Кто подскажет как реализовать более грамотно.
Здравствуйте, Аноним, Вы писали:
А>Делаю так: объявил виртуальный оператор == в базовом классе как чистый. А>Кроме того непонятно совершенно как решать такую задачу на проверку совместимости в шаблоне: мы знаем что типы могут быть указателями или переменные.
Если нужно именно сравнение:
struct base_element
{
virtual ~base_element(){}
virtual bool equal_to(const base_element* r) const throw() = 0;
};
#include <functional>
template<>
struct std::equal_to<base_element*>
{
bool operator()(const base_element* x, const base_element* y) const { return x && y ? x->equal_to(y) : x == y; } // последняя проверка на то, что оба элемента равны 0.
};
template<class T, class Compare = std::equal_to<T> >
class myset
{
Compare cmp_;
// использование компаратора:bool is_equal(const T& x, const T& y) const throw() { return cmp_(x,y); }
};
Здравствуйте, byleas
Спасибо за овтет.
Но есть проблемы с определением функцией наследникам
bool derivedclass::equal_to(const base* r) const
{
derivedclass* p=dynamic_cast< derivedclass*>(const_cast< base*> (r));
return a==p->getA();
}
есть 2 класса для которых приведение типа не работает. эти классы виртуально наследуют класс B. вот код ниже
class A{virtual a()=0;}
class B:public A;{virtual a(){};}
class C:virtual public B {virtual a(){};}
class D:virtual public B {virtual a(){};}
class E: public C,public D {a();};
так воть для класса D и C динамическое приведение не работает. Как быть?
E>class B : protected A {
E>class C : protected A {
E>
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Добрый день, Erop! Спасибо за ответ. E>Здравствуйте, Аноним, Вы писали: E>Если объекты разных типов не могут быть равны друг другу, то можно, например, так:
У меня была такая мысль, как вы предлоджили. Но подумал, что решение неверное так как я перегрузка тут не работала.
То есть: если в одном классе есть функция с параметром А*, а в другом классе такая же функция с параметром В* (где В наследник А),то в таком случае я всегда, считал что это 2 разные функции. Вот и проверил. Оказывается, я ошибался =) Видимо, что тут работает автоматичечкое приведение указателя класса А.
class A { bool isEqu( const A& );}
class B { bool isEqu( const B& );}
B b;
A* a=new B;
b.isEqu(a); // здесь вызывается B::isEqu
MX>class A { bool isEqu( const A& );}
MX>class B { bool isEqu( const B& );}
MX>B b;
MX>A* a=new B;
MX>b.isEqu(a); // здесь вызывается B::isEqu
// Что бы так не было, в B надо было написать using A::isEqu
// Но обычно, это не нужно и неудобно. Удобно, наоборот, явно указывать что с чем ты сравниваешь...
// В моём коде, кстати, *a == b отработает адекватно. Вызовутся нужные методы от нужных аргументов ;)
MX>
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском