Я работаю над проектом, где мне нужно иметь возможность динамически создавать объекты типа Audio_Device
или типы, которые производятся от Audio_Device
. Я пытаюсь использовать шаблон «Factory», чтобы достичь этого. Идея заключается в том, что строка «ID» будет зарегистрирована на заводе, а также соответствующий указатель функции на функцию, которая существует внутри Audio_Device
, которая порождает новое устройство. Когда я вызываю factory->Create_Device("IdString");
, код должен искать указатель функции, связанный с идентификатором, и вызывать функцию с помощью указателя функции и возвращать новый объект соответствующего типа.Элемент функции Указатели и объект Заводской шаблон
я извинюсь теперь масса кода прийти:
Вот устройство завода заголовок:
class Device_Factory
{
public:
Device_Factory();
virtual ~Device_Factory();
void Register_Device(std::string id,pDevice_Creation_Function pCreateDeviceFunction);
Audio_Device* Create_Device(std::string id,Memory::Pool* pool=nullptr);
private:
std::map<std::string,pDevice_Creation_Function>*m_pFactory_Map;
//map used to get function pointer that will spawn an instance of the class specified with the string key.
std::map<std::string,pDevice_Creation_Function>::iterator iter;
};
и реализация:
Device_Factory::Device_Factory()
{
m_pFactory_Map = new std::map<std::string,pDevice_Creation_Function>();
}
Device_Factory::~Device_Factory()
{
delete m_pFactory_Map;
}
void Device_Factory::Register_Device(std::string id,pDevice_Creation_Function pCreateDeviceFunction){
m_pFactory_Map->insert(std::make_pair(id,pCreateDeviceFunction));
}
Audio_Device* Device_Factory::Create_Device(std::string id,Memory::Pool* pool){
iter=m_pFactory_Map->find(id);
pDevice_Creation_Function p= iter->second;
//some sort of call to function pointer here
}
А теперь Audio_Device
код :
class Audio_Device;
typedef Audio_Device* (Audio_Device:: *pDevice_Creation_Function)(Memory::Pool* pool);
class Audio_Device: public Device
{
protected:
virtual Audio_Device* Create_Device(Memory::Pool* pool=nullptr);
/*Functions to describe how the class modifies the audio signal*/
bool GetNeedsInputWrite();
void SetNeedsInputWrite(bool value);
bool GetWillModifySignal();
void SetWillModifySignal(bool value);
/*--------------------------------------------------------------*/
private:
bool m_requiresInputWriteToProcess;
bool m_willModifySignal;
std::map<std::string, void*>* m_pParameters;
std::map<std::string, void*>::iterator iter;
/*Read and write buffers*/
Audio::AudioRingBuffer* m_pInputBuffer;
Audio::AudioRingBuffer* m_pOutputBuffer;
/*----------------------*/
public:
Audio_Device(Memory::Pool* pool=nullptr);
virtual ~Audio_Device();
virtual void* Process(void* data);
void SetBuffers(Audio::AudioRingBuffer* input,Audio::AudioRingBuffer* output);
/*Parameter management*/
void RegisterParameter(std::string id,void* location);
void* GetParameter(std::string id);
/*--------------------*/
constexpr static const pDevice_Creation_Function Device_Creation_Function=&Audio_Device::Create_Device;
};
template<typename ParameterType> void AssignToDeviceParameter(std::string parameter_id,ParameterType value,Audio_Device* device)
{
*(ParameterType*)device->GetParameter(parameter_id)=value;
}
}
и реализация:
Audio_Device::Audio_Device(Kraken::Memory::Pool* pool):Device::Device(pool)
{
m_pParameters = new std::map<std::string, void*>();
SetNeedsInputWrite(false);
SetWillModifySignal(true);
m_pInputBuffer=m_pOutputBuffer=nullptr;
}
Audio_Device::~Audio_Device()
{
delete m_pParameters;
m_pParameters=nullptr;
m_pInputBuffer=nullptr;
m_pOutputBuffer=nullptr;
}
void Audio_Device::SetBuffers(Audio::AudioRingBuffer* input,Audio::AudioRingBuffer* output){
if (input!=nullptr) {
m_pInputBuffer=input;
}
if (output!=nullptr) {
m_pOutputBuffer=output;
}
}
void* Audio_Device::Process(void* data)
{
/*The Basic Process:
Wipes input buffer and writes silence to the output buffer.
the void* data can be used to pass information to the function. in this implementation the function merely passes the adress of the data back in order to complete the return for the function.
*/
m_pInputBuffer->Flush();
Audio::Sample_Stereo_d samp;
samp.m_Channel_1=0;
samp.m_Channel_2=0;
for (int i =0; i<m_pOutputBuffer->Buffer_Size(); ++i) {
m_pOutputBuffer->Push(&samp);
}
return data;
}
bool Audio_Device::GetNeedsInputWrite(){
return m_requiresInputWriteToProcess;
}
void Audio_Device::SetNeedsInputWrite(bool value){
m_requiresInputWriteToProcess=value;
}
bool Audio_Device::GetWillModifySignal(){
return m_willModifySignal;
}
void Audio_Device::SetWillModifySignal(bool value){
m_willModifySignal=value;
}
void Audio_Device::RegisterParameter(std::string id,void* location){
m_pParameters->insert(std::make_pair(id, location));
}
void* Audio_Device::GetParameter(std::string id){
iter= m_pParameters->find(id);
return iter->second;
}
Audio_Device* Audio_Device::Create_Device(Memory::Pool* pool){
return new(pool)Audio_Device(pool);
}
У меня есть пространство имен бизнес и пулы памяти происходит так, пожалуйста, игнорировать это. Цель состоит в том, чтобы быть в состоянии иметь такой код:.
Device_Factory* factory = new Device_Factory();
factory->Register_Device("ID", Audio_Device::Device_Creation_Function);
Это зарегистрирует параметр (это работает прямо сейчас) А затем функция Audio_Device* Create_Device(std::string id,Memory::Pool* pool=nullptr);
выполнить такой код:
Audio_Device* Device_Factory::Create_Device(std::string id,Memory::Pool* pool){
iter=m_pFactory_Map->find(id);
pDevice_Creation_Function p= iter->second;
//where pDevice_Creation_Function is a member function pointer.
//and then somehow call it to return a new object.
}
Моя основная проблема заключается в том, что все различные синтаксисы вызова функции-члена, которые я нашел, похоже, не работают. Например, (device.*Device_Creation_Function)(args)
не работает для меня. Итак, каков правильный способ вызова указателя на функцию-член? или что является лучшим способом для достижения концепции, которую я попытался описать?
Любая помощь любого рода была бы замечательной, и дайте мне знать, могу ли я дать разъяснение, потому что я знаю, что я бросаю на вас стек кода.
Благодаря
В вашем контейнере карты вместо этого вы можете использовать шаблон шаблона шаблона (http://en.wikipedia.org/wiki/Template_method_pattern), чтобы создать экземпляр любого класса аудио, который вам нужен. – Huy
Не могли бы вы дать мне пример кода, как это может выглядеть с моим кодом? –
iter = m_pFactory_Map-> find (id); if (iter! = m_pFactory_Map-> end()) {return iter-> second-> createNewInstance(); } // Например. – Huy