2013-11-06 2 views
1

У меня есть структура BaseStorage, которая хранит различные данные во время выполнения, и структуру BaseStatic, которая содержит BaseStorage (или производные) typedef и «статические» данные, которые не изменяются и считываются из нескольких экземпляров структуры Holder. Holder имеет указатель на один из них, const BaseStatic* для доступа к данным только для чтения, общим данным и BaseStorage* в качестве своего личного магазина информации. «Статические» данные в BaseStatic по-прежнему заполняются во время выполнения (считанные из файла); он не постоянный!Как создать структуру «виртуальный» typedef?

Идея состоит в том, что BaseStatic имеет определенный набор данных и функций только для чтения, которые будут совместно использоваться 1: N среди множества экземпляров Holder. Каждый Holder также будет иметь информацию о времени выполнения, специфичную для своего экземпляра, которая должна соответствовать производному типу BaseStatic. Таким образом, это то, что делает производный материал BaseStorage, он содержит определенную информацию о времени выполнения, которой нужен тип BaseStatic. Holder сам также хранит данные и имеет функции, которые одинаковы среди всех Holder s; это не инертный контейнер.

Мне нужен производный BaseStorage в паре с каждым производным BaseStatic. Будет много из этих производных пар.

struct BaseStorage 
{ 
int something[2]; 
}; 

struct BaseStatic 
{ 
typedef BaseStorage Storage; 

//members and stuff 
}; 


struct DerivedStorage : public BaseStorage 
{ 
std::string somethingelse; 
}; 

struct DerivedStatic : public BaseStatic 
{ 
typedef DerivedStorage Storage; 

//other things 
}; 


struct Holder 
{ 
const BaseStatic* base; 
BaseStorage* storage; 
}; 

У меня есть функция-строитель, которая делает некоторые вещи, среди которых заселение хранилища. Единственный способ, которым я могу думать, делать это с помощью шаблонов, например, так:

template<typename T> Holder& builder(const T* base) //receives a BaseStatic 
{ 
Holder& holder = ...; 

//add to a list, etc 

holder.base = base; 
holder.storage = new T::Base(); 
} 

Однако, что собирается привести много шаблонных функций получения сделанных компилятором для очень пустяка (доступ к одной тип!). Кроме того, у меня никогда не будет параметров для моего конструктора T :: Base (если все структуры не имеют одинаковых!). Я уверен, что это ужасно и в других отношениях.

Есть ли способ сохранить тип, к которому можно получить доступ практически от BaseStatic без использования шаблонов? Там должен быть лучший способ.

Существуют различные ограничения, которые привели меня к этой настройке, поэтому я приношу свои извинения, если это уродливо.

+0

Есть виртуальный интерфейс в' BaseStorage' и/или ' BaseStatic' или вы просто используете наследование как альтернативный способ компоновки? (Я не вижу виртуальных деструкторов, поэтому я спрашиваю). –

+1

Вы можете добавить виртуальный метод к 'BaseStatic' под названием' virtual BaseStorage * CreateStorage() {return новый BaseStorage;} '.' Der ivedStatic' переопределит его, чтобы прочитать 'BaseStorage * DerivedStatic :: CreateStorage() {вернуть новый DerivedStorage; } '. –

ответ

0

Я использовал комментарий Реймонда Чена и создал этот метод в BaseStatic:

Storage* CreateStorage() const {return new Storage();} 

и переопределить его в DerivedStatic с:

Storage* CreateStorage() const {return new Storage();} 
0

Templating не так плохо, как вы, кажется, думаете, что это так. Любое полиморфное решение, скорее всего, потребует своего рода использования RTTI, что потребует сравнения и непрямого ветвления - потенциально более или менее дорогостоящего, чем набор шаблонных функций, и в зависимости от ваших требований это может быть плохим, хорошим или более вероятным, бессмысленным. Помните, что только один шаблон будет создан на основе уникального набора параметров шаблона, поэтому только один на базу T в вашем случае.

Одно решения вашей проблемы конструктора является использование C++ 11 VARIADIC шаблон арг:

template<typename T, typename ...Args> 
Holder builder(const T* base, Args ...args) //receives a BaseStatic 
{ 
    Holder holder; 

    //add to a list, etc 

    holder.base = base; 
    holder.storage = new typename T::Storage(args...); 
    return holder; 
} 

Обратите внимание, что для этой работы, выведенные типы хранения должны использовать закрытое наследование с BaseStorage, иначе Storage typedef становится неоднозначным.

Теперь это может взорвать множество функций в зависимости от объема вашего проекта, но помните - «еще не оптимизируйте."

Смежные вопросы