Указатель базового класса для класса шаблона, который использует параметр шаблона в данных члена

Для следующего класса шаблона

template <class T> class Arbitrary {
protected:
    vector<T> ObjectArray;
public:
    Arbitrary(){}   
};

Я хочу, чтобы у меня был вектор указателей базового класса, я знаю, что мне нужно использовать интерфейсный класс, но я не могу заставить его работать, любые предложения будут с благодарностью.

1 ответ

Решение

[..] Я хочу со временем написать vector<Arbitrary*> name;

Arbitrary это шаблон, а не тип. Чтобы "получить" тип из него, вам нужно "применить" его к другому типу (например, int). Это дает вам Arbitrary<int> как тип "результата". Этот процесс называется созданием шаблона.

Если вы хотите вектор с объектами любого возможного типа, который мог быть создан из шаблона Arbitraryзатем вам нужно дать им общий тип (такой, что каждый объект "является" объектом этого общего типа). Это потому что std::vector хранит только объекты одного типа.

Чтобы объекты "ведут себя" (в смысле наличия некоторого типа) по-разному, даже если они "имеют" общий тип, вам нужно сделать их (или, скорее, их общий тип) полиморфными. Это сделано, давая некоторому общему типу virtual функция. (И поскольку вы хотите удалять / уничтожать объекты через "интерфейс", представленный общим типом, вам нужно сделать деструктор виртуальным!)

struct ArbitraryBase {
  // Add "common interface" functions here, as virtual
  virtual ~ArbitraryBase() = 0; // pure virtual to avoid creating objects
};
inline ArbitraryBase​::~ArbitraryBase() {}

template<typename T>
struct Arbitrary : ArbitraryBase {
  // whatever
};

Теперь, чтобы действительно иметь возможность использовать это полиморфное свойство и не стать жертвой нарезки объектов, вам нужно использовать семантику ссылок или указателей:

std::vector<ArbitraryBase *> objects;

Вместо сырых указателей вы должны рассмотреть умные указатели, такие как std::unique_ptr<ArbitraryBase> если objects вектор должен иметь право собственности на объекты или иным образом использовать std::reference_wrapper<ArbitraryBase> в случае, если время жизни объектов надежно обрабатывается чем-то другим.

Но если вы не добавите какой-либо общий интерфейс (больше функций виртуального члена) в ArbitraryBase тогда вы в основном изобретаете std::any / boost::any, Так что лучше используйте эти хорошо протестированные реализации.

Другие вопросы по тегам