Я хочу создать базовый класс для моих классов. Как мне это сделать правильно?
#include <string>
#include <iostream>
#include <vector>
#include <set>
#include <utility>

template <typename T>
struct Node
{
	Node<T>* left_child{};
	Node<T>* right_child{};
	T value{};
};

template <typename KeyType, typename ValueType>
struct AA_node
{
	KeyType key{};
	ValueType value{};
	AA_node<KeyType, ValueType>* left{};
	AA_node<KeyType, ValueType>* right{};

	AA_node(KeyType k, ValueType v) : key(k), value(v), left(nullptr), right(nullptr) {}
};

template <typename T>
struct DL_node
{
	T value{}; 
	DL_node<T>* prev{};
	DL_node<T>* next{};

	//DL_node(int d) : data(d), prev(nullptr), next(nullptr) {}
};

template <typename T>
class PersistentArray
{
private:

	// base version
	T* base{};

	// size of base version
	int size{};

	// container for roots of versions
	std::vector<Node<T>*> versions{};

	std::vector<std::pair<int, int>> parent_children_relation{};

	// recursive function to build tree with leafs as elemnts of _array in [_l..._r] and _node as root of version
	void buildTree(Node<T>* _node, T* _array, int _left_border, int _right_border);

	// recursive function to add new version by changing one value in one of previous version
	void add(Node<T>* _to, Node<T>* _from, int _left_border, int _right_border, int _position, T _new_value);

	// recursive function to get element of specific node
	T get(Node<T>* _node, int _left_border, int _right_border, int _position);

	// recursive function to count leaves in a tree
	int countLeaves(Node<T>* _node);

	// print from [_left] to [_right] 
	void printSlice(T* _arr, int _left, int _right);

public:

	// constructor with empty array of _size * elements
	PersistentArray(int _size);

	// constructor with _array of _size * elements
	PersistentArray(T* _arr, int _size);

	// destructor
	~PersistentArray();

	// set element to base version
	void setElementToBase(int _index, T _value);

	// change element by index in a specific version with new value  
	void changeVersion(int _number_of_version, int _change_index, T _new_value);

	// add new version by changing one value in one of previous version
	void addVersion(int _root_position, int _change_inde, T _new_value);

	// print all versions as a table
	void printAllVersions();

	// get size of a specific version
	int versionSize(int _number_of_version);

	// get a specific version as array
	T* getArray(int _number_of_version);

	// delete element in a specific version
	void deleteElement(int _root_position, int _delete_index);

	// insert a new value in a specific version
	void insertElement(int _root_position, int _insert_index, T _new_value);

	// get a root of specific version
	Node<T>* getVersion(int _number_of_version);
	
	// get number of versions
	int sizeVersions();
};

template <typename T>
class PersistentDoublyLinkedList
{
private:

	// base version
	DL_node<T>* base;

	// size of base version
	int size{};

	// container for roots of versions
	std::vector<Node<T>*> versions{};

	std::vector<std::pair<int, int>> parent_children_relation{};

	// recursive function to build tree with leafs as elemnts of _array in [_l..._r] and _node as root of version
	void buildTree(Node<T>* _node, DL_node<T>* _list_head, int _left_border, int _right_border);

	// recursive function to add new version by changing one value in one of previous version
	void add(Node<T>* _to, Node<T>* _from, int _left_border, int _right_border, int _position, T _new_value);

	// recursive function to get element of specific node
	T get(Node<T>* _node, int _left_border, int _right_border, int _position);

	// making a single node with data and assign it to base
	void initDL(T _data);

	// recursive function to count leaves in a tree
	int countLeaves(Node<T>* _node);

public:

	// constructor that creats one node with _data in it
	PersistentDoublyLinkedList(T _data);

	// constructor that creates double linked list from array
	PersistentDoublyLinkedList(T* _arr, int _size);

	// constructor that takes _head as base
	PersistentDoublyLinkedList(DL_node<T>* _head);

	// destructor
	~PersistentDoublyLinkedList();

	// adding data to end
	void append(T _data);

	// print from [_left] to [_right]
	void printSlice(DL_node<T>* _head, int _left, int _right);

	// get size of a specific DL_list
	int getSize(DL_node<T>* _head);

	// get element by index in DL list
	T getElement(DL_node<T>* _head, int _index);

	// change element by index in a specific version with new value  
	void changeVersion(int _number_of_version, int _new_position, T _new_value);

	// add new version by changing one value in one of previous version
	void addVersion(int _root_position, int _new_position, T _new_value);

	// print all versions as a table
	void printAllVersions();

	// get size of a specific version
	int versionSize(int _number_of_version);

	// get a specific version as array
	DL_node<T>* getList(int _number_of_version);

	// delete element in a specific version
	void deleteElement(int _root_position, int _delete_index);

	// insert a new value in a specific version
	void insertElement(int _root_position, int _insert_index, T _new_value);

	// get a root of specific version
	Node<T>* getVersion(int _number_of_version);

	// get number of versions
	int sizeVersions();
};

template <typename KeyType, typename ValueType>
class PersistentAssociativeArray
{
private:
	AA_node<KeyType, ValueType>* base{};
	std::vector<Node<ValueType>*> versions{};
	std::vector<Node<KeyType>*> key_versions{};
	std::vector<KeyType> keys{};
	std::vector<std::pair<int, int>> parent_children_relation{};

	void buildTreeValue(Node<ValueType>*, AA_node<KeyType, ValueType>*, int, int, std::vector<KeyType>);
	void buildTreeKey(Node<KeyType>*, AA_node<KeyType, ValueType>*, int, int, std::vector<KeyType>);

	template <typename X>
	void add(Node<X>*, Node<X>*, int, int, int, X);
	void addValue(Node<ValueType>*, Node<ValueType>*, int, int, int, ValueType);
	void addKey(Node<KeyType>*, Node<KeyType>*, int, int, int, KeyType);

	template <typename X>
	X get(Node<X>*, int, int, int);
	ValueType getValue(Node<ValueType>*, int, int, int);
	KeyType getKey(Node<KeyType>*, int, int, int);

	int countLeaves(Node<ValueType>* _node);
	AA_node<KeyType, ValueType>* insertRecursive(AA_node<KeyType, ValueType>*, KeyType, ValueType, std::vector<KeyType>);
	AA_node<KeyType, ValueType>* searchRecursive(AA_node<KeyType, ValueType>*, KeyType, std::vector<KeyType>);
	int sizeRecursive(AA_node<KeyType, ValueType>*);
	void printSliceRecursive(AA_node<KeyType, ValueType>*, int, int);
	void printKeys();
public:
	PersistentAssociativeArray(AA_node<KeyType, ValueType>*);
	PersistentAssociativeArray(KeyType, ValueType);
	PersistentAssociativeArray(KeyType*, ValueType*, int);
	~PersistentAssociativeArray();

	void setElementToBase(KeyType, ValueType);
	ValueType getElement(AA_node<KeyType, ValueType>*, KeyType);
	ValueType getElementByIndex(AA_node<KeyType, ValueType>*, int, std::vector<KeyType>);
	void addVersion(int, KeyType, ValueType);
	void printSlice(AA_node<KeyType, ValueType>*, int, int);
	void printAllVersions();
	void changeVersion(int, KeyType, ValueType);
	int versionSize(int);
	int getSize(AA_node<KeyType, ValueType>*);
	AA_node<KeyType, ValueType>* getAssociativeArray(int);
	void deleteElement(int, KeyType);
	void insertElement(int, int, KeyType, ValueType);
	Node<ValueType>* getVersion(int _number_of_version);
	// get number of versions
	int sizeVersions();
};

template <typename ValueType>
class Convert
{
private:

	// recursive function to insert by key with value
	//static AA_node<std::string, ValueType>* insertRecursive(AA_node<std::string, ValueType>*, std::string, ValueType, std::vector<KeyType>);

	// recursive function to get element of specific node
	static ValueType get(Node<ValueType>* _node, int _left_border, int _right_border, int _position);

	static int nodeSize(Node<ValueType>* _node);

public:
	// TODO : _version_size in deep

	// fuction that creates an object of PersistentArray class from tree
	static PersistentArray<ValueType> toArray(Node<ValueType>* _version);

	// fuction that creates an object of PersistentDoublyLinkedList class from tree
	static PersistentDoublyLinkedList<ValueType> toDLList(Node<ValueType>* _version);

	// fuction that creates an object of PersistentAssociativeArray class from tree
	template<typename KeyType>
	static PersistentAssociativeArray<KeyType, ValueType> toAssociativeArray(Node<ValueType>* _version, KeyType* _keys);
};