Как объявить элементы данных, которые являются объектами любого типа в классе - PullRequest
12 голосов
/ 07 июня 2011

В этой части я пытаюсь объявить в классе B список, который может содержать объекты класса A любого типа, такие как A , A , A .Я намереваюсь добавить объекты A в список во время выполнения:

#include <list>

template <class T> class A {};

class B {
    template<class T> std::list<A<T>*> objects;
};

Кажется, что создание списка, подобного этому, должно работать, но компиляция выдает ошибку:

Строка 6:ошибка: элемент данных 'objects' не может быть шаблоном элемента

компиляция прекращена из-за -Wfatal-errors.

Может кто-нибудь объяснить, почему это не работает и как я могу это исправитьэто?

Ответы [ 5 ]

14 голосов
/ 07 июня 2011

Это не так, как работает C ++.Если вы хотите сгруппировать разные объекты вместе, они должны иметь как минимум отношение some .Наличие экземпляров одного и того же шаблона класса не означает, что они связаны, это совершенно разные типы.Если вам нужен список A<T>* s, лучше составьте список указателей базового класса и операций пересылки через виртуальные функции:

class A_base{
public:
  virtual void foo() = 0;
  virtual ~A_base() { }
};

template<class T>
class A : public A_base{
public:
  void foo(){
    // ...
  }
};

class B{
  std::list<A_base*> objects;
};
5 голосов
/ 07 июня 2011

Переменные-члены не могут быть шаблонами. Шаблонами могут быть только члены функции . Вам придется шаблонизировать окружающий класс B вместо:

template <class T>
class B {
  std::list<A<T>*> objects;
};
3 голосов
/ 07 июня 2011

К сожалению, у вас не может быть шаблонных переменных . Единственная возможность объявить данные члена - создать шаблон класса:

template<class T>
class B {
    std::list<A<T>*> objects;
};
2 голосов
/ 07 июня 2011

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

В двух словах, вы преобразуете статическую диспетчеризацию, разрешенную шаблонами, в динамическую диспетчеризацию.через пользовательское дерево наследования, которое вы настраиваете на лету.Вместо хранения A<T> вы создаете новый тип, имеющий желаемый общий интерфейс, и с помощью некоторого шаблона / наследования voodoo этот новый тип хранит A<T> без фактического раскрытия T.Так что A<int> и A<double> и A<A<std::list<A<int> > > > и some_type_that_looks_like_A_but_really_isnt - все сводятся к одному типу.

Но у вас должен быть общий интерфейс, независимый от этого параметра.Если вы не можете, все становится сложнее.

Boost.Any является хорошим примером, как и std::shared_ptr [, который использует стирание типа, чтобы запомнить, как удалить указатель, переданный вэто даже перед лицом неполиморфного наследования].

0 голосов
/ 07 июня 2011

Создайте B шаблон класса так же, как вы сделали A шаблон класса:

template<class T> 
class B {
    std::list<A<T>*> objects;
};
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...