0

Я работаю над проектом, где мне нужно иметь возможность динамически создавать объекты типа 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) не работает для меня. Итак, каков правильный способ вызова указателя на функцию-член? или что является лучшим способом для достижения концепции, которую я попытался описать?

Любая помощь любого рода была бы замечательной, и дайте мне знать, могу ли я дать разъяснение, потому что я знаю, что я бросаю на вас стек кода.

Благодаря

+0

В вашем контейнере карты вместо этого вы можете использовать шаблон шаблона шаблона (http://en.wikipedia.org/wiki/Template_method_pattern), чтобы создать экземпляр любого класса аудио, который вам нужен. – Huy

+0

Не могли бы вы дать мне пример кода, как это может выглядеть с моим кодом? –

+0

iter = m_pFactory_Map-> find (id); if (iter! = m_pFactory_Map-> end()) {return iter-> second-> createNewInstance(); } // Например. – Huy

ответ

1

Они не работают, потому что они на самом деле не работает в такой ситуации. Функция создания устройства должна быть как обычная функция, не являющаяся членом. Это может быть статический член (очевидно, тривиальная оболочка для «нового»). Синтаксис вызова функции-члена не должен использоваться, не существует «виртуального конструктора» :-) Во-вторых, может быть проще просто построить желаемый объект надлежащего производного класса по мере необходимости (посредством «нового»). Вы уверены, что вам действительно нужны «Factory» и string id? Также карта, созданная «новым» в конструкторе и удаленная в деструкторе, может быть лучше элемента данных, а не указателя ... И карта параметров в AudioDevice несколько сомнительна. Действительно ли класс AudioDevice должен манипулировать неизвестными параметрами типа void *? Может быть, они являются членами производного класса (где у них будут соответствующие имена и правильные типы и будут ли они надлежащим образом обработаны)?

+0

Карта параметров предназначена для другой части системы. Проект - это цифровая аудио рабочая станция, и эти устройства представляют собой различные аудио-плагины. идея состоит в том, что обработчик парня будет знать идентификатор параметра и типа и, следовательно, имеет необходимую информацию для назначения переменной. это всего лишь средство группировки различных типов параметров вместе аккуратно. Что касается устройства устройства, можете ли вы дать мне пример кода того, что вы описываете? –

+0

'class X: public B {public: static B * newX (MemPool * p) {return new X (p); } X (MemPool *);/* ... * /};/* newX - это функция, которая вам нужна. Это может быть когда-либо не член и вызвано по мере необходимости. «новый X (пул)» может быть лучше. */' – user3221894

1

Функции указателей функций работают с виртуальными функциями, но для их вызова требуется объект.

Это противоречит цели использования этой функции для создания объекта в первую очередь.

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