2016-01-08 25 views
0

我有一個基類內的虛函數和該基類的幾個派生類。當其他人被調用時,我沒有接到虛擬函數的調用。錯過了一個虛函數調用

我的基類:

class C_ANY 
{ 
public: 
    enum EDataTypeID { 
     eANY = 1, eBOOL, eSINT, eINT, eDINT, eLINT, eUSINT, 
     eUINT, eUDINT, eULINT, eBYTE, eWORD, eDWORD, eLWORD, 
     eDATE, eTIME_OF_DAY, eDATE_AND_TIME, eTIME, eREAL, eLREAL, eSTRING, 
     eWSTRING 
    }; 

    C_ANY(void); 
    virtual ~C_ANY() {} 

    virtual EDataTypeID getDataTypeID() const { 
     return C_ANY::eANY; 
    } 
}; 

我的派生類

class C_ANY_ELEMENTARY : public C_ANY { 

public: 

    C_ANY_ELEMENTARY() : 
     C_ANY() { 
    } 

    virtual ~C_ANY_ELEMENTARY() { 
    } 

    virtual EDataTypeID getDataTypeID() const { 
     return C_ANY::eANY; 
    } 
}; 

class C_ANY_BIT : public C_ANY_ELEMENTARY { 

public: 
    virtual ~C_ANY_BIT() { 
    } 

protected: 
    C_ANY_BIT() : 
     C_ANY_ELEMENTARY() { 
    } 
}; 

class C_BOOL : public C_ANY_BIT { 

public: 
    typedef bool ValueType; 

    C_BOOL(void); 

    virtual ~C_BOOL() { 
    } 

    virtual EDataTypeID getDataTypeId() const { 
     return C_ANY::eBOOL; 
    } 
}; 

class C_ANY_STRING : public C_ANY_ELEMENTARY { 

public: 
    virtual ~C_ANY_STRING() {} 

    C_ANY_STRING() { 
    } 
}; 

class C_WSTRING : public C_ANY_STRING 
{ 
public: 
    C_WSTRING() { 
    } 

    virtual ~C_WSTRING() { 
    } 

    virtual EDataTypeID getDataTypeID() const { 
     return C_ANY::eWSTRING; 
    } 
}; 

我創建一個std ::地圖列表存儲派生類指針的基礎上使用的數據類型的列表。因爲所有派生類都來自基類C_ANY我返回類型爲C_ANY類的指針。

C_ANY * DatatypeHandler::CreateDataTypeInstance(C_ANY::EDataTypeID type) 
{ 
    switch (type) 
    { 
     case C_ANY::eANY: { 
     C_ANY *ptr = new C_ANY(); 
     return ((ptr != NULL) ? ptr : NULL); 
     } 
     break; 

     case C_ANY::eBOOL: { 
     C_BOOL *ptr = new C_BOOL(); 
     return ((ptr != NULL) ? ptr : NULL); 
     } 
     break; 

     case C_ANY::eWSTRING: { 
     C_WSTRING *ptr = new C_WSTRING(); 
     return ((ptr != NULL) ? ptr : NULL); 
     } 
     break; 
    } 

    return NULL; 
} 

typedef std::map<C_ANY::EDataTypeID, C_ANY*> DataTypeList; 
DataTypeList  _dataTypeList; 

void CreateDataTypeInstance(C_ANY::EDataTypeID type) 
{ 
    DataTypeList::const_iterator iter = _dataTypeList.find(type); 
    if (iter == _dataTypeList.end()) 
    { 
     _dataTypeList.insert(make_pair(type, DatatypeHandler::getInstance().CreateDataTypeInstance(type))); 
    } 
} 

檢查如下數據類型值:

void checkDataType(C_ANY::EDataTypeID type) { 

printf("\n UpdataDataVar : %d, %d", type,_dataTypeList[type]->getDataTypeID()); 
    DataTypeList::const_iterator iter = _dataTypeList.find(type); 
    printf("\n iterator : %d, %d", iter->first, iter->second->getDataTypeID()); 
} 

我得到的輸出如下。我不明白什麼是真正的問題,爲什麼它打印正確的值爲eANYeWSTRING和爲什麼不爲eBOOL

UpdataDataVar : 2, 1 <<<< Issue is This <<<<<< 
iterator : 2, 1  <<<< Issue is This <<<<<< 
UpdataDataVar : 22, 22 
iterator : 22, 22 
UpdataDataVar : 1, 1 
iterator : 1, 1 
+2

備註:請不要命名類似MACRO_S。你不需要在new之後進行nullptr測試(它會拋出一個異常,除非你使用新的(std :: nothrow)T) –

+1

@DieterLücking,而且甚至**如果使用no-throw版本的'new' ,'return((ptr!= NULL)?ptr:NULL);'仍然和'return ptr'具有完全相同的效果。 – SergeyA

+0

side-topic:[爲什麼不是匈牙利符號](http://stackoverflow.com/questions/111933/why-shouldnt-i-use-hungarian-notation) – dwanderson

回答

4

您在C_BOOL得到錯誤的結果,因爲錯誤的方法名稱:virtual EDataTypeID getDataTypeId() const,而不是virtual EDataTypeID getDataTypeID()const。在C++ 11 覆蓋說明符將有助於避免此類錯誤。

1

你建議你讓getDataTypeIDANY類中有一個純虛函數。這將服務於兩個目的:

  1. 這將突出你的代碼(在C_BOOL類的重載函數不正確的名稱)的問題 - 你會發現有一個編譯錯誤,當您嘗試使用C_BOOL對象
  2. 它也會阻止創建C_ANY類型的對象 - 這是一件好事,因爲這些對象不能賦予任何意義。

附註(除在評論中已經提到):

  • 你並不需要提供瑣碎的構造函數和析構函數。也就是說,

C_ANY_ELEMENTARY() : 
    C_ANY() { 
} 

virtual ~C_ANY_ELEMENTARY() { 
} 

只是打字噪音(幾乎有一些陰暗的角落,但你並不需要擔心這些。)。在所有的層次,你唯一需要的析構函數是

virtual ~C_ANY() {} 
  • 你在你的switch語句不要多break秒 - 你反正回來。
+0

正確的答案,但零/空/缺少類型可能是有用(但應該明確) –

+0

@DieterLücking,同意100% - 這就是爲什麼C_NULL應該是集合中的另一種類型,而不是C_ANY本身。 – SergeyA