Заранее спасибо за чтение. Это придирчивый вопрос дизайна, потому что у меня есть адекватное решение, но вопрос, если нет лучшего способа с помощью шаблонов, с которым я не очень опытен.
У меня есть ряд типов таблиц данных (производных от абстрактного класса DataTable), которые мне нужно хранить. Я написал абстрактный класс «DataTableIndex», в котором хранятся векторные DataTable * и который выполняет общую работу, общую для всех DataTableIndexes - выполняет поиск, реализует шаблон Proxy, поэтому таблицы загружаются только при необходимости, проверяется на наличие ошибок и т. Д.
Затем я делю его на подклассы для каждого типа таблицы, единственная причина, по которой мне нужно это сделать, заключается в том, что каждый тип таблицы имеет специальную функцию, которая должна быть вызвана для его загрузки.
Я бы хотел как-то избежать этого подкласса DataTableIndex через шаблоны, потому что существует множество подклассов DataTable.
class DataTableIndex
{
// various functions to implement lookup, Proxy and error checking
// functionality common to all DataTableIndexes.
// This code needs access to _lookupTable and _theTables
DataTable* getTable( int tableNum );
private:
// These functions call the appropriate user interface function for loading
// a table of the subclass' type.
// They are called by more general non-virtual public functions
virtual bool loadIndex( vector<LookupEntry*>& returnLookupTable ) = 0;
virtual DataTable* loadTable( int tableNum ) = 0;
vector<LookupEntry*> _lookupTable;
vector<DataTable*> _theTables;
UserInterface* UI;
};
В этом классе есть очень простые подклассы, которые в основном указывают на функции в классе пользовательского интерфейса, которые фактически открывают и анализируют файл таблицы данных.
class TableTypeA_Index : public DataTableIndex
{
virtual bool loadIndex( vector<LookupEntry*>& returnLookupTable )
{
return UI->loadTableAIndex( _lookupTable );
}
virtual DataTable* loadTable( int tableNum )
{
return UI->loadTableTypeA( _lookupTable[ tableNum ] );
}
};
Это работает адекватно. Но я чувствую, что должен быть в состоянии передать «loadTableTypeA», например, в DataTableIndex через параметр шаблона, поэтому мне не нужно создавать его подкласс.
Другая причина, по которой я хотел бы использовать шаблоны, заключается в том, что я не хочу постоянно приводить DataTable * к фактическому типу таблицы. Несмотря на то, что я знаю во время компиляции, какой тип таблицы это должен быть, я чувствую, что должен использовать dynamic_cast <> для проверки ошибок, но я не хочу, чтобы вызывающая функция getTable () должна была делать это каждый раз (это часто вызывается).
Мое идеальное решение:
1) обобщить класс DataTableIndex в шаблон, используя параметры шаблона, заменяющие LookupEntry * и DataTable * в _lookupTable и _theTables. Это устранит кастинг.
2) отобразить соответствующие функции пользовательского интерфейса для загрузки нужного типа таблицы без подклассов.
Так что в основном я хотел бы, чтобы этот класс выглядел так (как-то)
DataTableIndex< LookupEntryTypeAMatlab,
TableTypeA,
loadTableAIndex(),
loadTableTypeA() > theTypeAIndex;
Я немного подумал о классах политики, но у меня сложилось впечатление, что в этом случае я просто перенесу подклассы на что-то другое.