Полиморфизм членов шаблона, - возможно ли такое?
От: Аноним  
Дата: 06.02.04 10:48
Оценка:
Добрый день, уважаемый all.

Вопрос следующего характера:
если есть абстрактный родительский класс A,
class A
{
public:
   virtual void f()=0;
};


и его наследник класс B

class B: public A
{
public:
   virtual void f() { cout<< "B::f()" <<endl; }
};


как можно реализовать использование, например, std::list<A*> вместо std::list<B*>, например, в таком случае:

void func(const std::list<A*> & lst)
{
   for (std::list<A*>::const_iterator it=lst.begin();it!=lst.end();it++)
      (*it)->f();
}

int main ()
{
   B tmp;
   std::list<B*> lst;
   lst.push_back(&tmp);
   func(lst);
   return 0;
}


Собственно, если бы функция main выглядела так:
int main ()
{
   A * tmp=new B();
   std::list<A*> lst;
   lst.push_back(tmp);
   func(lst);
   return 0;
}


Никаких бы проблем не было, но но всегда удобно хранить список указателей на родительские классы..
Re: Полиморфизм членов шаблона, - возможно ли такое?
От: Lorenzo_LAMAS  
Дата: 06.02.04 11:05
Оценка:
Тарабарщина какая-то. В чем тогда смысл контейнеров полиморфных указателей, ежели тебе не охота использовать конейнеры указателей на базовый класс? Ну уж раз тебе это так не нравится, то тогда соответственно и тип функции задавай void fun(const std::list<B *> &)

Типы std::list<A *> и std::list<B *> — совершенно разные, никак не связанные между собой.
Of course, the code must be complete enough to compile and link.
Re: Полиморфизм членов шаблона, - возможно ли такое?
От: alnsn Великобритания http://nasonov.blogspot.com
Дата: 06.02.04 11:38
Оценка:
wrote:

> как можно реализовать использование, например, std::list<A*> вместо

> std::list<B*>, например, в таком случае:
>
> [ccode]
> void func(const std::list<A*> & lst)
> {
> for (std::list<A*>::const_iterator
> it=lst.begin();it!=lst.end();it++)
> (*it)->f();
> }

Посмотри в бусте transform_iterator

--
Александр Насонов,
Независимый консультант и разработчик ПО
alnsn-mycop@yandex.ru (для более быстрого ответа удалите -мусор из адреса)
Posted via RSDN NNTP Server 1.8 beta
Re[2]: Полиморфизм членов шаблона, - возможно ли такое?
От: Аноним  
Дата: 06.02.04 11:40
Оценка:
Здравствуйте, Lorenzo_LAMAS, Вы писали:

L_L>Тарабарщина какая-то. В чем тогда смысл контейнеров полиморфных указателей, ежели тебе не охота использовать конейнеры указателей на базовый класс? Ну уж раз тебе это так не нравится, то тогда соответственно и тип функции задавай void fun(const std::list<B *> &)


L_L>Типы std::list<A *> и std::list<B *> — совершенно разные, никак не связанные между собой.


Представь себе ситуацию, когда в существующую и работающую систему надо ввести, например, идентификацию имен используемых классов. Достаточно логично было бы ввести класс-предок, который бы делал следуещее:
class A
{
public:
   void info()    {    cout<< typeid(*this).name() <<endl;    }    
   virtual ~A() {};
};


Тогда достаточно было бы добавить его в список потомков используемых классов, чтобы реализовать примерно так:
void func(A * a)   {    a->info();   }
void func(const std::list<A*> & lst)
{
   for (std::list<A*>::const_iterator it=lst.begin();it!=lst.end();it++)
      (*it)->info();
}

Вы можете возразить, что гораздо легче было бы сделать шаблонную функцию, которая именно этим и занимается:
template<class T>
void func(const T & a)   {    cout<<typeid(a).name()<<endl;   }

но вот проблема заключается в том, что для контейнеров эта функция выдаст имя контейнера, а не его элементов, т.е.
class std::list<class B *,class std::allocator<class B *> >


а, например, при глобальной индексации объектов, или для сериализации требуется применить функцию ко всем элементам контейнера, что значит получить в нашем случае что-то вроде
class B
class B
class B


Извиняюсь, если слишком запутано изложил свои мысли, — воюю с этим уже 2-й день и ничего умного в голову не приходит..
Re[3]: Полиморфизм членов шаблона, - возможно ли такое?
От: ArtDenis Россия  
Дата: 06.02.04 12:22
Оценка:
Здравствуйте, <Аноним>, Вы писали:

А>
А>class A
А>{
А>public:
А>   void info()    {    cout<< typeid(*this).name() <<endl;    }    
А>   virtual ~A() {};
А>};
А>


Для таких вещей можно использовать нечто похожее на фабрику объектов. В фабрике будет находится указатель на typeinfo и имя класса. По указателю на базовый класс такая фабрика будет возвращать имя. Естественно, каждый класс придётся в этой фабрике регистрировать.

Денис.
... << RSDN@Home 1.1.2 stable >>
[ 🎯 Дартс-лига Уфы | 🌙 Программа для сложения астрофото ]
Re: Полиморфизм членов шаблона, - возможно ли такое?
От: Tonal- Россия www.promsoft.ru
Дата: 06.02.04 21:31
Оценка:
А>Вопрос следующего характера:
А>если есть абстрактный родительский класс A, и его наследник класс B
А>
А>class A {
А>public:
А>   virtual void f()=0;
А>};
А>
А>class B: public A
А>{
А>public:
А>   virtual void f() { cout<< "B::f()" <<endl; }
А>};

А>void func(const std::list<A*> & lst)
А>{
А>   for (std::list<A*>::const_iterator it=lst.begin();it!=lst.end();it++)
А>      (*it)->f();
А>}

А>//как можно реализовать использование, например, 
А>//std::list<A*> вместо std::list<B*>, например, в таком случае:
А>int main ()
А>{
А>   B tmp;
А>   std::list<B*> lst;
А>   lst.push_back(&tmp);
А>   func(lst);
А>   return 0;
А>}
А>


А>Собственно, если бы функция main выглядела так:

А>
А>int main ()
А>{
А>   A * tmp=new B();
А>   std::list<A*> lst;
А>   lst.push_back(tmp);
А>   func(lst);
А>   return 0;
А>}
А>


А>Никаких бы проблем не было, но но всегда удобно хранить список указателей на родительские классы..


Действительно почему-то нет шаблонных конструкторов копирования для стандартных контейнеорв, но зато есть шаблонные конструкторы "заполнения" из интервала, вот их-то и можно использовать:
func(list<A*>(lst.begin(), lst.end()));

или написать простенькую функцию преобразования:
template <class Out, class In>
inline Out cont_cvt(const In& in) {
  return Out(in.begin(), in.end());
}
//Использование
func(cont_cvt<list<A*> >(lst));


Можно попытаться использовать шаблонный параметр шаблона, тогда вызов будет короче:
template <
  class Out, class In, 
  template <class, class> class Cont, 
  template <class> class Alloc
> 
inline Cont<Out, Alloc<Out> > 
cont_cvt(const Cont<In, Alloc<In> >& in) {
  return Cont<Out, Alloc<Out> >(in.begin(), in.end());
}
//Использование
func(cont_cvt<A*>(lst));


Правда не все компиляторы понимают этот синтаксис, да и количество параметров для контейнеров различно (и может быть разным, для разных STL-ей.

Компиляторы, понимающие этот синтаксис, несколько различаются в трактовке.
MinGW 3.2.3 например, скомпилил вот такой вариант cont_cvt, а Intel 7.1 отказался:
template <class Out, class In, template <class> class Cont>
inline Cont<Out> cont_cvt(const Cont<In>& in) {
  return Cont<Out>(in.begin(), in.end());
}
... << RSDN@Home 1.1.0 stable >>
Re: Полиморфизм членов шаблона, - возможно ли такое?
От: Vladimir Levchuk Украина  
Дата: 09.02.04 10:21
Оценка:
Здравствуйте, Аноним, Вы писали:

а так:
template<typename InputIterator>
void func(InputIterator begin, InputIterator end)
{
   for (InputIterator it = begin; it != end; it++)
   {
       (*it)->f();
   }
};


А>Добрый день, уважаемый all.


А>Вопрос следующего характера:

А>если есть абстрактный родительский класс A,
А>
А>class A
А>{
А>public:
А>   virtual void f()=0;
А>};
А>


А>и его наследник класс B


А>
А>class B: public A
А>{
А>public:
А>   virtual void f() { cout<< "B::f()" <<endl; }
А>};
А>


А>как можно реализовать использование, например, std::list<A*> вместо std::list<B*>, например, в таком случае:


А>
А>void func(const std::list<A*> & lst)
А>{
А>   for (std::list<A*>::const_iterator it=lst.begin();it!=lst.end();it++)
А>      (*it)->f();
А>}

А>int main ()
А>{
А>   B tmp;
А>   std::list<B*> lst;
А>   lst.push_back(&tmp);
А>   func(lst);
А>   return 0;
А>}
А>


А>Собственно, если бы функция main выглядела так:

А>
А>int main ()
А>{
А>   A * tmp=new B();
А>   std::list<A*> lst;
А>   lst.push_back(tmp);
А>   func(lst);
А>   return 0;
А>}
А>


А>Никаких бы проблем не было, но но всегда удобно хранить список указателей на родительские классы..
--------------------------
WBR,
Leva mailto:leva@nm.ru,
ICQ: 106191183
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.