0

ポリモーフィズムと継承が正確に何であるかについて間違った考えを持っているかもしれませんが、基本的に私がやろうとしているのは、classBをclassAから派生させ、 classAの純粋仮想メンバー関数をオーバーライドするclassBを作成することです。


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に含まれる関数の特定のリストをオーバーライドします。

これはどのように達成できますか?テンプレートを使用する必要がありますか(可能であれば)?

4

2 に答える 2

1

答えとしてコメントを持参してください:

CCodeBlock::クラス内でメンバー関数を宣言するときに必要ありませんCCodeBlock

于 2013-02-26T03:32:40.727 に答える
1

コードにいくつか問題があります。メンバー宣言には、資格としてクラス名を付けないCCodeBlock::でください(つまり、宣言から削除する必要があります)。そのままにしておくと、コードの形式が悪くなります。

それに加えて、派生型のデストラクタ暗黙的に基本クラスのデストラクタを呼び出すので、そうすべきではありません。手動で呼び出すと、ベースサブオブジェクトが2回破棄され、未定義の動作が発生する可能性があります(ベースデストラクタが簡単でない場合)。

これで、コードの特定の問題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

于 2013-02-26T03:58:43.670 に答える