Метод
IMagicSpell::ShowDebugInfo
у тебя обращается к приватному полю
IMagicSpell::SpellInfo
. Это поле недоступно для наследников, т.к. является приватным.
Конструктор-же,
Fireball::Fireball
, у тебя работает с приватным полем
Fireball::SpellInfo
.
Поля
IMagicSpell::SpellInfo
и
Fireball::SpellInfo
являются разными, расположены в разных областях памяти объекта
Fireball
и в принципе никак не могут пересечься своими данными.
Размер твоего
Fireball
будет с два
MagicSpellInfo
плюс размер таблицы виртуальных символов.
От причины можно перейти к достижению желаемого поведения.
Самое главное - второй экземпляр
MagicSpellInfo
в иерархии - лишний.
Fireball::SpellInfo
является дублирующим, лишним полем, которое не позволяет добиться необходимой тебе функциональности. Ведь в обоих твоих классах тебе надо работать с одними данными, с полем
IMagicSpell::SpellInfo
.
Просто удаляем
Fireball::SpellInfo
.
Fireballclass Fireball: public IMagicSpell {
public:
Fireball() {
SpellInfo.Name = "Огненный шар";
SpellInfo.Description = "Мощный огненный шар, сметающий все на своем пути.";
SpellInfo.Type = fire;
SpellInfo.MinDamage = 30;
SpellInfo.MaxDamage = 50;
SpellInfo.Range = 40;
SpellInfo.Distance = 120;
}
virtual ~Fireball() {}
virtual void Use() {
cout << "Boom!" << endl;
}
};
Но теперь мы не скомпилируемся. Компилятор напишет что
IMagicSpell::SpellInfo
является приватным и недоступен для потомков. Исправить это тоже очень легко.
Есть
три вида секций доступа к полям и функциям класса:
private
- приватный доступ, только для экземпляра текущего класса;
protected
- ограниченный доступ, только для экземпляров текущего класса и всех публичных наследников; доступ ограничивается при ограниченном или приватном наследовании;
public
- публичный доступ, для всех пользователей экземпляров класса.
Нам надо сменить права доступа к
IMagicSpell::SpellInfo
с приватного на ограниченный. В этом случае экземпляры
Fireball
смогут обращаться к
IMagicSpell::SpellInfo
как к своему ограниченному полю.
IMagicSpellclass IMagicSpell {
protected:
MagicSpellInfo SpellInfo;
public:
virtual ~IMagicSpell() {}
virtual void Use() {}
MagicSpellInfo GetInfo() {
return this->SpellInfo;
}
void ShowDebugInfo() {
cout << "Название: " << SpellInfo.Name << endl;
cout << "Описание: " << SpellInfo.Description << endl;
cout << "Тип: " << SpellInfo.Type << endl;
cout << "Мин. урон: " << SpellInfo.MinDamage << endl;
cout << "Макс. урон: " << SpellInfo.MaxDamage << endl;
cout << "Расстояние: " << SpellInfo.Distance << endl;
cout << "Радиус: " << SpellInfo.Range << endl;
}
};
В таком виде ты сможешь добиться желаемой функциональности. Но куда более важно чтобы тебе было понятно, как именно ты этого добился.