rpg.cpp:
#include <iostream>
using namespace std;
/*
模拟一个游戏场景
有一个英雄:初始所有属性为1
atk,def,apd,hp
游戏当中有以下3种武器
长剑Sword: 装备该武器获得 +1atx,+1def
短剑Blade: 装备该武器获得 +1atk,+1spd
斧头Axe: 装备该武器获得 +1atk,+1hp
要求英雄写一个函数:
equipweapon 装备武器
实现效果:装备不同武器英雄获得不同的属性加成
*/
class Hero;
class Weapon
{
int atk;
public:
Weapon():atk(1){}
virtual ~Weapon(){}
void set_atk(int atk)
{
this->atk = atk;
}
int get_atk()
{
return atk;
}
virtual void equip(Hero &h);
};
class Sword:public Weapon
{
int def;
public:
Sword():def(1){}
void set_def(int def)
{
this->def = def;
}
int get_def()
{
return def;
}
void equip(Hero &h) override;
};
class Blade:public Weapon
{
int spd;
public:
Blade():spd(1){}
void set_spd(int spd)
{
this->spd = spd;
}
int get_spd()
{
return spd;
}
void equip(Hero &h) override;
};
class Axe:public Weapon
{
int hp;
public:
Axe():hp(1){}
void set_hp(int hp)
{
this->hp = hp;
}
int get_hp()
{
return hp;
}
void equip(Hero &h) override;
};
class Hero
{
int atk;
int def;
int spd;
int hp;
Weapon * current_weapon;
public:
Hero():atk(1),def(1),spd(1),hp(1),current_weapon(new Weapon){}
~Hero(){delete current_weapon;}
void set_atk(int atk)
{
this->atk = atk;
}
int get_atk()
{
return atk;
}
void set_def(int def)
{
this->def = def;
}
int get_def()
{
return def;
}
void set_spd(int spd)
{
this->spd = spd;
}
int get_spd()
{
return spd;
}
void set_hp(int hp)
{
this->hp = hp;
}
int get_hp()
{
return hp;
}
void equip_weapon(Weapon *w);
void show();
};
void Weapon::equip(Hero &h)
{
int new_atk = h.get_atk() + this->get_atk();
h.set_atk(new_atk);
}
void Sword::equip(Hero &h)
{
Weapon::equip(h);
int new_def = h.get_def() + def;
h.set_def(new_def);
}
void Blade::equip(Hero &h)
{
Weapon::equip(h);
int new_spd = h.get_spd() + spd;
h.set_spd(new_spd);
}
void Axe::equip(Hero &h)
{
Weapon::equip(h);
int new_hp = h.get_hp() + hp;
h.set_hp(new_hp);
}
void Hero::equip_weapon(Weapon *w)
{
delete current_weapon;
current_weapon = w;
w->equip(*this);
}
void Hero::show()
{
cout << "******** 英雄属性 ********" << endl
<< " " << "atk = " << atk << endl
<< " " << "def = " << def << endl
<< " " << "spd = " << spd << endl
<< " " << "hp = \t" << hp << endl
<< "**************************" << endl;
}
int main()
{
Hero h1,h2,h3;
h1.equip_weapon(new Sword);
h2.equip_weapon(new Blade);
h3.equip_weapon(new Axe);
h1.show();
h2.show();
h3.show();
return 0;
}
通过虚函数解决菱形继承产生的二义性问题
A --------公共基类
/ \
B C --------中间子类
\ /
D --------汇集子类
B类中会继承A类的成员,C类中也继承A类的成员,
D类中汇集成B和C中的所有成员 ------>导致A类中的内容,在D类中存在两份
有可能造成代码膨胀
#include <iostream>
using namespace std;
class A
{
public:
int a;
A():a(9){cout << "A构造" << endl;}
};
class B:public A
{
public:
int b;
B():b(0){cout << "B构造" << endl;}
};
class C:public A
{
int c;
public:
//因为继承顺序是先继承B,再继承A,所以B先构造结束,后A构造结束,最后C构造结束
//和初始化列表中的调用顺序无关
C():c(6),A(){cout << "C构造" << endl;}
void show();
};
class D:public B,public C
{
void show_a()
{
//cout << a << endl; //因为中间基类中存在两种方式可以找到a
cout << B::a << endl; //存在于B类中的A类继承下来的a
cout << C::a << endl; //存在于C类中的A类继承下来的a
}
};
int main()
{
C c1;
c1.show();
return 0;
}
虚继承(virtual)
#include <iostream>
using namespace std;
class Person
{
int age; //4字节
string name; //32字节 +4对齐 36
public:
Person(){}
Person(int age,string name):age(age),name(name){}
virtual void show(); //虚指针 8字节
}; //48
class Stu:public Person // 继承Person 48
{
double score; //56
public:
Stu(){}
Stu(int age,string name,double score):Person(age,name),score(score){}
void show(); //对虚指针指向的虚函数表中的show进行重写
}; //56
void Person::show()
{
cout << "Person 中的show函数 " << endl;
cout << "age = " << age << endl;
cout << "name = " << name << endl;
}
void Stu::show()
{
cout << "Stu 中的show函数 " << endl;
cout << "score = " << score << endl;
}
int main()
{
cout << sizeof (Person) << endl;
cout << sizeof (Stu) << endl;
Stu s1(18,"张三",99);
Person &rp = s1;
rp.show();
rp.Person::show();
return 0;
}
在菱形继承中,由于汇集子类中会保存两份公共基类的内容造成二义性问题,所以通常两个中间子类会虚继承公共基类 ------>在汇集子类中就只存在一份公共基类的内容
#include <iostream>
using namespace std;
class A
{
public:
int a;
A():a(9){cout << "A构造" << endl;}
};
//中间子类虚继承公共基类A
class B:virtual public A
{
public:
int b;
B():b(0),A(){cout << "B构造" << endl;}
};
class C:virtual public A
{
int c;
public:
//因为继承顺序是先继承B,再继承A,所以B先构造结束,后A构造结束,最后C构造结束
//和初始化列表中的调用顺序无关
C():c(6),A(){cout << "C构造" << endl;}
void show();
};
class D:public B,public C
{
//汇集子类的构造函数中对于公共基类的构造,需要直接调用公共基类的构造函数即可
D():B(),C(),A(){}
void show_a()
{
//不加virtual,有两份A中的a
cout << a << endl; //由于我们使用了虚继承,所以D类中只有一份从公共基类中继承下来的a
cout << B::A::a << endl;
cout << C::A::a << endl;
}
};
int main()
{
C c1;
c1.show();
return 0;
}