当前位置: 动力学知识库 > 问答 > 编程问答 >

c++ - Pointer to member template classes

问题描述:

AbstractFieldCollection is the base class of hardwareMissingAlarm, etc.

hardwareMissingAlarm belongs to another class that is a template.

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

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

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

Then in another function I'm reading the vector like this:

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))

{

.....

}

}

and pDev is the Device object, however pDev->*pAF returns NULL. In fact when I'm printing &Device::hardwareErrorAlarm, &Device::hardwareMissingAlarm the result is 1. I don't know what I'm doing wrong.

isRaised is a method that belongs to the class AbstractAlarmField.

Thanks in advance.

网友答案:

You provided almost no code but it seems like you are storing an abstract object by value, not by reference or pointer. This may lead to object slicing and any kind of memory problem as a consequence. Try to use AbstractAlarmField& as the type of Device fields instead.

网友答案:

It is not useful to convert a member pointer X C::* to Y C::*. The Standard allows it as a reinterpret_cast or C-style cast, but with entirely unspecified results (unless you convert back to the original type). You would be better off using a virtual functor to safely get the AbstractAlarmField subobject:

#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))

If it might be useful, you could also easily add an overload

virtual const AbstractAlarmField& get(const Device& dev) const;
分享给朋友:
您可能感兴趣的文章:
随机阅读: