2013-02-26 115 views
0

我可能有錯誤的觀念上正是多態性與繼承,但基本上我想要做的是有CLASSBCLASSA派生,並創建一個CLASSB它覆蓋CLASSA的純虛成員函數,如下所示:多態性/繼承問題與虛擬類的成員函數


CLASSA:

///////////////// 
// CodeBlock.h // 
///////////////// 

typedef enum { 
    CCBT_UNDEFINED, 
    CCBT_FUNCTION, 
    //... 
} CODE_BLOCK_TYPE; 

class CCodeBlock { 
public: 
    CCodeBlock::CCodeBlock(); 
    CCodeBlock::CCodeBlock(CString& source, DWORD startPos); 
    CCodeBlock::~CCodeBlock(); 
    virtual CODE_BLOCK_TYPE CCodeBlock::GetType() = 0 

    CString m_code; 
    DWORD m_startPos; 
    DWORD m_length; 
    int m_numLines; 
} 

    /////////////////// 
// CodeBlock.cpp // 
/////////////////// 

//... 
CCodeBlock::CCodeBlock(CString& source, DWORD startPos) : m_code(source), m_startPos(startPos) { 
    m_length = m_code.GetLength(); 
} 

CODE_BLOCK_TYPE CCodeBlock::GetType() { 
    return CCBT_UNDEFINED; 
} 


CLASSB:

///////////////////// 
// FunctionBlock.h // 
///////////////////// 

#include "CodeBlock.h" 

class CFunctionBlock : public CCodeBlock { 
public: 
    CFunctionBlock::CFunctionBlock(); 
    CFunctionBlock::CFunctionBlock(CString& source, DWORD startPos); 
    CFunctionBlock::~CFunctionBlock(); 
    CODE_BLOCK_TYPE CFunctionBlock::GetType(); 
} 

    /////////////////////// 
// FunctionBlock.cpp // 
/////////////////////// 

//... 
CFunctionBlock::CFunctionBlock(CString& source, DWORD startPos) 
{ 
    m_code = source; 
    m_startPos = startPos; 
} 

CFunctionBlock::~CFunctionBlock() 
{ 
    CCodeBlock::~CCodeBlock(); 
} 

CODE_BLOCK_TYPE CFunctionBlock::GetType() 
{ 
    ////////////////////////////// 
    // >> NEVER GETS CALLED! << // 
    ////////////////////////////// 
    return CCBT_FUNCTION; 
} 


主:

CCodeBlock *block = new CFunctionBlock(L"function hello(){ print('hello') }", iPos) 
CODE_BLOCK_TYPE type = block->GetType(); // ALWAYS RETURNS CCBT_UNDEFINED! 


正如你所看到的,的GetType()總是返回 CCBT_UNDEFINED。請記住,CCodeBlock是CFunctionBlock的一個'通用'版本(以及其他一些志同道合的類,其中一些包含CCodeBlock'm_parent'成員變量),並且應該繼承任何CCodeBlock成員變量&成員函數,以及覆蓋CCodeBlock中包含的特定函數列表。

這是如何實現的?我是否需要訴諸使用模板(如果甚至可能的話)?

+3

順便說一句,當你在類「CCodeBlock」中聲明成員函數時,你不需要'CCodeBlock ::' – billz 2013-02-26 03:23:12

+1

而且,類型不匹配。 'CCodeBlock CFunctionBlock :: GetType()'vs'CODE_BLOCK_TYPE CCodeBlock :: GetType()'。這段代碼是否可以編譯? – Matthew 2013-02-26 03:25:43

+0

@billz是一個複製/粘貼錯字,CFunctionBlock :: GetType()例外 - 這似乎一直是問題。刪除'CFunctionBlock ::'後,block-> GetType()現在返回CCBT_FUNCTION。非常感謝!如果您將此作爲答案發布,我會爲您讚揚。 – RectangleEquals 2013-02-26 03:30:12

回答

1

帶註釋的答案:

你不需要CCodeBlock::在聲明中類的成員函數CCodeBlock

+0

實際的問題出現在CFunctionBlock中,而不是CCodeBlock中。但是,這足夠接近。再次感謝! – RectangleEquals 2013-02-26 03:37:32

1

有幾件事情你的代碼錯誤。會員聲明不應該有類名作爲資格(即CCodeBlock::應該從聲明中刪除)。將它留在那裏會使代碼生病。

除此之外,派生類型的析構函數將隱式地調用基類的析構函數,你不應該這樣做。如果您手動調用它,基礎子對象將被銷燬兩次,可能會導致未定義的行爲(如果基礎析構函數不重要)。

現在,隨着main代碼中的具體問題可能是更多這樣的:

CCodeBlock *block 
    = new CFunctionBlock(L"function hello(){ print('hello') }", iPos) 
CODE_BLOCK_TYPE type = block->CCodeBlock::GetType(); 
//       ^^^^^^^^^^^^ 

在C++中,符合條件的函數調用禁用動態調度。表達式block->GetType()將被分派到block指針指向的對象的動態類型的最終覆蓋。但是,如果添加限定條件:block->CCodeBlock::GetType(),則要求編譯器在CCodeBlock級別調用覆蓋。

+0

這很有道理。我已經從我的源中刪除了所有的基礎析構函數調用,謝謝!而且,就block塊的CCodeBlock :: GetType()而言,目標是改爲調用block-> GetType()調用block-> CFunctionBlock :: GetType(),這樣我就可以做到了一旦我從'CODE_BLOCK_TYPE CFunctionBlock :: GetType(); __CFunctionBlock ::'_中刪除_FunctionBlock.h_ – RectangleEquals 2013-02-26 05:29:04

+0

@RectangleEquals:你明白我在關於'block-> CCodeBlock :: GetType()'的回答中所說的話,對?我不確定是否足夠清楚:如果使用類名稱限定函數調用,則禁用動態分派並強制調用在該級別執行。 – 2013-02-26 13:57:22