2013-01-14 79 views
3

AbstractFieldCollection是hardwareMissingAlarm等的基类 hardwareMissingAlarm属于另一个作为模板的类。指向成员模板类的指针

alarmFieldCollection.push_back((AbstractAlarmField Device::*) &Device::hardwareMissingAlarm); 
alarmFieldCollection.push_back((AbstractAlarmField Device::*) &Device::hardwareErrorAlarm); 
alarmFieldCollection.push_back((AbstractAlarmField Device::*) &Device::badConfigAlarm);`` 

然后在另一个功能我在读向量是这样的:

for(int32_t i=0; i<alarmFieldCollection.size(); i++) 
{ 
    AbstractAlarmField Device::* pAF = alarmFieldCollection[i]; 
    std::cout << "isRaised: "<< pDev << std::endl; 
    if ((pDev->*pAF).isRaised(pContext)) 
    { 
      ..... 
    } 
} 

pDev是设备对象,但是pDev->*pAF回报NULL。事实上,当我印刷&Device::hardwareErrorAlarm,&Device::hardwareMissingAlarm的结果是1.我不知道我做错了什么。

isRaised是一种属于class AbstractAlarmField的方法。

在此先感谢。

+0

何处以及如何被'pDev'定义'? –

+1

为什么你将指针指向成员函数?如果他们真的是正确的类型,这是没有必要的。 –

+0

void execute(RequestEvent * pEvt,Device * pDev,Alarm_DataType&data)是标题。 pDev是具有所有字段(包括警报)的设备。 AbstractAlarmField是AlarmField的抽象类。 AlarmFields是模板,因此在从集合中获取字段时无法实例化,因为我试图将其转换为Abstract类 – user1977398

回答

2

你几乎没有提供代码,但它看起来像你存储一个抽象对象的价值,而不是通过引用或指针。这可能导致对象切片和任何类型的内存问题。尝试使用AbstractAlarmField&作为Device字段的类型。

+0

void execute(RequestEvent * pEvt,Device * pDev,Alarm_DataType&data)是标题。 pDev是具有所有字段(包括警报)的设备。 AbstractAlarmField是AlarmField的抽象类。 AlarmFields是模板,所以在从集合中获取字段时不能实例化,因为我试图将它转换为Abstract类。 – user1977398

0

将成员指针X C::*转换为Y C::*没有用。该标准允许将其作为reinterpret_cast或C风格转换,但其结果完全未指定(除非转换回原始类型)。你会使用虚拟仿函数安全地获得AbstractAlarmField子对象会更好:

#include <type_traits> 
#include <memory> 

struct AlarmGetter { 
public: 
    virtual ~AlarmGetter(); 
    virtual AbstractAlarmField& get(Device& dev) const = 0; 
}; 

template <typename T> 
struct AlarmMemberPtr 
    : public AlarmGetter { 
    static_assert(std::is_base_of<AbstractAlarmField, T>::value, 
        "Member type is not an AbstractAlarmField"); 
public: 
    explicit AlarmMemberPtr(T Device::*member) 
     : m_member(member) {} 
    virtual AbstractAlarmField& get(Device& dev) const { 
     return dev.*m_member; 
    } 
private: 
    T Device::*m_member; 
}; 

template <typename T> 
std::unique_ptr<AlarmGetter> make_alarm_getter(T Device::*member) { 
    std::unique_ptr<AlarmGetter> ptr(new AlarmMemberPtr<T>(member)); 
    return ptr; 
} 

// To populate: 
std::vector<std::unique_ptr<AlarmGetter>> alarmFieldCollection; 
alarmFieldCollection.push_back(make_alarm_getter(&Device::hardwareMissingAlarm)); 
alarmFieldCollection.push_back(make_alarm_getter(&Device::hardwareErrorAlarm)); 
alarmFieldCollection.push_back(make_alarm_getter(&Device::badConfigAlarm)); 

// To use: 
if (alarmFieldCollection[i]->get(*pDev).isRaised(pContext)) 

如果它可能是有用的,你也可以很容易地添加过载

virtual const AbstractAlarmField& get(const Device& dev) const; 
+0

问题是我具有相同的值:&Device :: hardwareMissingAlarm,&Device :: hardwareErrorAlarm和 &Device :: badConfigAlarm;那是1.我认为这不正确是不是? – user1977398

+0

并且在AlarmField中定义了从AbstractAlarmField继承的isRaised。一个设备(pDev)可以有多个alarmFields。 – user1977398

+0

指向成员的指针不能为1.但是,如果您尝试打印它们,它们可能会隐式转换为'bool',在这种情况下,确保您总是会得到“1”。你可能会发现'&Device :: hardwareMissingAlarm ==&Device :: hardwareErrorAlarm'是错误的。 – aschepler