指向成员模板类的指针

时间:2013-01-14 13:53:41

标签: c++

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的方法。

提前致谢。

2 个答案:

答案 0 :(得分:2)

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

答案 1 :(得分: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;