パターンPlayer
を実装しようとするクラスがあります。と呼ばれる基本クラスのメンバーが含まれています。クライアントからのデストラクタを呼び出すと、いくつかの問題が発生し、メモリ アクセス違反が発生します。開始日:Decorator
Player
Character
m_player
Player
main
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
ましCharacter
たCharacterDecorator
。
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;
}