我正在开发一个项目,我需要能够动态生成名为Audio_Device
的类型的对象或从Audio_Device
派生的类型。我一直在尝试使用“工厂”模式来实现这一目标。我们的想法是,“ID”字符串将在工厂注册,并且相应的函数指针指向存在于Audio_Device
内部的函数,该函数会生成新设备。当我调用factory->Create_Device("IdString");
时,代码应该查找与ID关联的函数指针,并通过函数指针调用函数并返回一个正确类型的新对象。
我现在要为大量代码道歉:
以下是设备工厂标题:
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 :(得分:1)
它们不起作用,因为它们在这种情况下确实不起作用。 “设备”创建功能应该像通常的非成员功能一样。它可能是一个静态成员(显然,“new”的简单包装)。不应该使用成员函数调用语法,不存在“虚拟构造函数”:-) 其次,根据需要(通过“new”)更简单地构造适当派生类的期望对象可能更好。你确定你真的需要“工厂”和字符串ID吗? 在构造函数中由“new”构造并在析构函数中删除的映射可能更好的数据成员,而不是指针... AudioDevice中的参数映射有些值得怀疑。真的AudioDevice类应该操作void *类型的未知参数吗?可能他们是派生类的成员(他们将拥有适当的名称和适当的类型,并将被适当地操纵)?
答案 1 :(得分:1)
成员函数指针可以很好地处理虚函数,但是你需要一个对象来调用它们。
这与首先使用该函数创建对象的目的相冲突。