指向成员模板类指针

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

提前感谢您的帮助。


pDev 是在哪里和如何定义的? - Olaf Dietsche
1
为什么要将成员函数指针转换类型?如果它们确实是正确的类型,这是不必要的。 - Olaf Dietsche
这是函数头:void execute(RequestEvent* pEvt, Device* pDev, Alarm_DataType& data)。pDev是具有所有字段(包括警报)的设备。AbstractAlarmField是AlarmField的抽象类。AlarmFields是模板,因此在从集合中获取字段时无法实例化,因此我尝试将其转换为抽象类。 - user1977398
“AbstractFieldCollection是hardwareMissingAlarm等的基类。” 这句话正确吗?还是AbstractAlarmField是hardwareMissingAlarm的基类? - Olaf Dietsche
2个回答

2

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


这是函数头:void execute(RequestEvent* pEvt, Device* pDev, Alarm_DataType& data)。pDev是包含所有字段(包括警报)的设备。AbstractAlarmField是AlarmField的抽象类。由于AlarmFields是模板,所以在从集合中获取字段时无法实例化,因此我尝试将其转换为抽象类。 - 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;

而isRaised是在继承自AbstractAlarmField的AlarmField中定义的。一个设备(pDev)可以有多个alarmFields。 - user1977398
指向成员的指针不能为1。但是,如果您试图打印它们,它们可能已经隐式转换为“bool”,在这种情况下,您肯定会得到“1”。您可能会发现&Device::hardwareMissingAlarm == &Device::hardwareErrorAlarm是错误的。 - aschepler
我得到了这个编译错误:在这一行中,出现了“<”标记之前的预期构造函数、析构函数或类型转换错误:std::unique_ptr<AlarmGetter> make_alarm_getter(T Device::*member) { - user1977398
我在这行代码中遇到了同样的错误:error: expected constructor, destructor, or type conversion before '<' token。代码如下:std::unique_ptr<AlarmGetter> make_alarm_getter(T Device::*member)。 - user1977398
通过你的代码,我得到了这个编译错误:'AbstractAlarmField' 是 'AlarmField<AlarmField_DataType<4u>, 4u>' 的一个不可访问的基类。 - user1977398
显示剩余8条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接