1

パターンPlayerを実装しようとするクラスがあります。と呼ばれる基本クラスのメンバーが含まれています。クライアントからのデストラクタを呼び出すと、いくつかの問題が発生し、メモリ アクセス違反が発生します。開始日:DecoratorPlayerCharacterm_playerPlayermain

Character* createBaseClass();

// more forward declarations

int main (int argc, char* const argv[]) 
{
    Player* mainCharacter = new Player(createBaseCharacter());

    delete mainCharacter;   // Crashes when calling delete

    return 0;
}

Character* createBaseCharacter()
{
    return Character::Builder()
        .name("Dylan")
        .description("Super bad-ass hero of the game")
        .build();
}

次の呼び出しシーケンスを持つ でdeleteオペレーターを呼び出した直後にエラーが発生します。mainCharacter

Player::~Player()
{
    delete m_armor;
    delete m_weapon;
    delete m_player;  // calls Character's destructor
}

次に、のデストラクタCharacter:

Character::~Character()
{
    // works fine
    //
    delete m_abilityAttributes;  
    m_abilityAttributes = NULL;
    delete m_primaryAttributes;
    m_primaryAttributes = NULL;
}

ただし、奇妙なことは、このデストラクタが 2 回呼び出されているように見えることです。上記の実行が完了すると、デバッガを実行すると逆アセンブリに移動し、「スカラー削除デストラクタ」を介して、Characterデストラクタを再度呼び出すように見えます。Playerと呼ばれるのインターフェースCharacterDecorator:

ここに画像の説明を入力

クラッシュ時のコール スタック:

ここに画像の説明を入力

のデストラクタを呼び出すCharacterDecoratorと、次のようにCharacterのデストラクタが呼び出されます。

Character::~Character()
{
    // Crashes with Access Violation
    //
    delete m_abilityAttributes;  
    m_abilityAttributes = NULL;
    delete m_primaryAttributes;
    m_primaryAttributes = NULL;
}

この時点で、私は完全に混乱していますCharacterDecorator。デストラクタが具体的な実装を通じて呼び出されることに加えて、抽象インターフェイスを通じてデストラクタが再度呼び出される理由がわかりません。さらに、デストラクタを追加してCharacterDecoratorも問題は解決しないようです。

参考までに、 の実装と のインターフェースを含めPlayerましCharacterCharacterDecorator

class CharacterDecorator : public Character
{
public:

    virtual Armor* getArmor() const = 0;
    virtual Weapon* getWeapon() const = 0;
};

Player:

Player::Player()
{}

Player::Player(Character* player)
    :m_player(player)
    ,m_weapon(0)
    ,m_armor(0)
{}

Player::Player(Character* player, Weapon* weapon, Armor* armor)
    :m_player(player) 
    ,m_weapon(weapon)
    ,m_armor(armor)
{}

Player::~Player()
{
    delete m_armor;
    delete m_weapon;
}

// getters
Armor* Player::getArmor() const
{
    return m_armor;
}

Weapon* Player::getWeapon() const
{
    return m_weapon;
}

// additional methods ...

Character:

Character::Character()
{}

Character::Character(const Builder& builder)
    :m_name(builder._name)
    ,m_description(builder._description)
    ,m_abilityAttributes(builder._abilityAttributes)
    ,m_primaryAttributes(builder._primaryAttributes)
{}

Character::Character(const Character& rhs)
{
    m_name = rhs.m_name;
    m_description = rhs.m_description;
    m_abilityAttributes = new AbilityAttributes();
    m_primaryAttributes = new PrimaryAttributes();
    *m_abilityAttributes = *rhs.m_abilityAttributes;
    *m_primaryAttributes = *rhs.m_primaryAttributes;
}

Character::~Character()
{
    delete m_abilityAttributes;
    m_abilityAttributes = NULL;
    delete m_primaryAttributes;
    m_primaryAttributes = NULL;
}

// additional methods ...

// Builder pattern methods
//
Character::Builder::Builder()
    : _abilityAttributes(0), _primaryAttributes(0)
{}

Character* Character::Builder::build()
{
    return new Character(*this);
}

Character::Builder& Character::Builder::abilityAttributes(AbilityAttributes* value)
{
    _abilityAttributes = value;
    return *this;
}

Character::Builder& Character::Builder::primaryAttributes(PrimaryAttributes* value)
{
    _primaryAttributes = value;
    return *this;
}
4

2 に答える 2

2

あなたのPlayerクラスは から継承しCharacterDecorator、それは から継承しCharacterます。したがって、Playerオブジェクトでデストラクタを呼び出すと、m_player オブジェクトを削除し (そのCharacterデストラクタを呼び出して)、オブジェクトの基本Character部分で再び削除しPlayerます。あなたがやりたいことではないという事実に加えて、 を作成したときPlayerに、デフォルトのCharacterコンストラクターが呼び出されてベースオブジェクトが作成され、これはの部分でCharacter何も初期化しないという問題もあります。つまり、デストラクタで削除するおよびのようなフィールドです。CharacterPlayerm_abilityAttributesm_primaryAttributesCharacter

Characterさて、あなたのにも 5 月があるようですPlayer。おそらく、'CharacterDecorator CharacterDecorator Character::Builder Character` ベースのベースを初期化/構築するために使用されるポインターの代わりに、Playerコンストラクターに参照を持たせたいと思うでしょう)。Character::BuilderCharacterCharacter(and you may have to have aconstructor taking aobject to initialize its

(注: m_player メンバーが a を指すようにすることCharacterは、私にとって危険信号でした)

于 2013-01-04T01:43:52.837 に答える