2013-01-14 72 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