Указатель базового класса для класса шаблона, который использует параметр шаблона в данных члена
Для следующего класса шаблона
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
, Так что лучше используйте эти хорошо протестированные реализации.