面向对象(类相关)
C++面向对象核心Demo:王者荣耀英雄类体系
#include <iostream>
#include <string>
using namespace std;
// 英雄基类:包含纯虚函数的抽象类,定义所有英雄的通用属性和行为
class Hero {
private:
string name; // 英雄名(私有成员,子类不可直接访问)
int hp; // 生命值
int mana; // 蓝量
protected:
string camp; // 阵营(保护成员,子类可直接访问)
public:
// 构造函数 实例化类对象的时候自动调用
//1、默认构造函数 无参,不写也行,默认就带
Hero(){
}
// 2、重载无参构造,给成员默认值
// Tips:函数重载
Hero() : name("未知英雄"), hp(3000), mana(500), camp("无阵营") {
cout << name << ":默认构造,峡谷新生!" << endl;
}
// 3、重载带参构造,传入值并赋给对应成员
Hero(string n, int h, int m, string c) : name(n), hp(h), mana(m), camp(c) {
cout << name << ":带参构造,加入" << camp << "阵营!" << endl;
}
// 4、复制构造函数:值传递对象时触发,传进来一个同类型对象
Hero(const Hero& other) : name(other.name), hp(other.hp), mana(other.mana), camp(other.camp) {
cout << name << ":复制构造,镜像召唤!" << endl;
}
// 析构函数:类对象销毁时自动执行,一般用于释放动态申请的内存,防止内存泄漏。
// 虚析构函数:保证基类指针释放派生类对象时析构完整
// Tips:虚函数
virtual ~Hero() {
cout << name << ":退出峡谷,析构销毁!" << endl;
}
// 普通成员函数:设置/获取私有属性
void setName(string n) { name = n; }
string getName() const { return name; }
int getHp() const { return hp; }
// 运算符重载:重载[],通过下标访问英雄属性
string operator[](int index) const {
if (index == 0) return name;
else if (index == 1) return to_string(hp);
else if (index == 2) return camp;
else return "无效属性索引";
}
// 虚函数:英雄普通攻击(子类可重写,实现不同普攻效果)
virtual void normalAttack() const {
cout << name << ":基础普攻,造成物理伤害!" << endl;
}
// 纯虚函数:英雄核心技能(抽象行为,子类必须实现)
virtual void coreSkill() const = 0;
//--------------静态 static-------------------------
// 静态成员可不通过对象,直接 类名::成员名访问,所有类对象共享这一个
// 静态成员:属于类,所有英雄共享的峡谷属性,
static string gameName;
// 静态成员函数:打印游戏信息,属于类可通过对象/类名调用
static void showGameInfo() {
cout << "当前游戏:" << gameName << " | 5v5峡谷对战" << endl;
}
// 单参构造:实现自动类型转换(字符串直接转为英雄名)
Hero(string n) : name(n), hp(3000), mana(500), camp("无阵营") {
cout << name << ":单参构造,快速创建!" << endl;
}
};
// 静态成员变量:类外初始化
string Hero::gameName = "王者荣耀";
// 派生类:射手英雄(公有继承英雄基类)
class Archer : public Hero {
private:
int attackRange; // 射手专属:攻击射程
static int archerCount; // 静态计数:当前峡谷射手数量
public:
// 派生类无参构造:必须显式调用基类构造
Archer() : Hero("鲁班七号", 3500, 400, "射手"), attackRange(800) {
archerCount++;
cout << getName() << ":射手构造,射程" << attackRange << "!" << endl;
}
// 带参构造
Archer(string n, int h, int m, string c, int r) : Hero(n, h, m, c), attackRange(r) {
archerCount++;
cout << getName() << ":射手构造,射程" << attackRange << "!" << endl;
}
// 派生类析构:自动调用基类析构
~Archer() override {
archerCount--;
cout << getName() << ":射手析构,峡谷射手数量-1!" << endl;
}
// 重写基类虚函数:射手专属普攻
void normalAttack() const override {
cout << getName() << ":射手普攻,远程物理伤害,射程" << attackRange << "!" << endl;
}
// 实现基类纯虚函数:射手核心技能
void coreSkill() const override {
cout << getName() << ":核心技能-无敌鲨嘴炮,超远程范围伤害!" << endl;
}
// 静态成员函数:获取当前峡谷射手数量
static int getArcherCount() {
return archerCount;
}
};
// 射手静态计数初始化
int Archer::archerCount = 0;
// 派生类:法师英雄(公有继承英雄基类)
class Mage : public Hero {
private:
int magicPower; // 法师专属:法术强度
public:
// 派生类构造:调用基类构造 无参,默认填充妲己信息
Mage() : Hero("妲己", 3000, 800, "法师"), magicPower(600) {
cout << getName() << ":法师构造,法强" << magicPower << "!" << endl;
}
Mage(string n, int h, int m, string c, int mp) : Hero(n, h, m, c), magicPower(mp) {
cout << getName() << ":法师构造,法强" << magicPower << "!" << endl;
}
// 重写基类虚函数:法师专属普攻
void normalAttack() const override {
cout << getName() << ":法师普攻,远程法术伤害,法强" << magicPower << "!" << endl;
}
// 实现基类纯虚函数:法师核心技能
void coreSkill() const override {
cout << getName() << ":核心技能-灵魂冲击,单体高额法术伤害!" << endl;
}
};
// 测试函数:基类指针/引用传参,实现多态
// 基类指针作形参,可传入任意派生类对象
void heroFight(Hero* hero) {
cout << "\n【峡谷对战】" << endl;
hero->normalAttack();
hero->coreSkill();
}
// 引用传递:不触发复制构造函数
void heroInfo(const Hero& hero) {
cout << "\n【英雄信息】" << endl;
cout << "姓名:" << hero[0] << " | 生命值:" << hero[1] << " | 阵营:" << hero[2] << endl;
}
// 值传递:触发复制构造函数
void heroCopy(Hero hero) {
cout << "\n【复制英雄】" << endl;
hero.normalAttack();
}
// 主函数:测试所有面向对象特性
int main() {
// 静态成员测试:类名/对象均可调用静态函数
cout << "===== 峡谷初始化 =====" << endl;
Hero::showGameInfo(); // 静态成员调用
Archer luBan; // 实例化射手鲁班
luBan.showGameInfo();
cout << "当前峡谷射手数量:" << Archer::getArcherCount() << endl;
// 继承与构造测试:派生类构造自动调用基类构造
cout << "\n===== 召唤英雄 =====" << endl;
Mage daJi; // 实例化法师对象
Archer houYi("后羿", 3800, 450, "射手", 900); //实例化射手对象
// 单参构造实现自动类型转换
Hero yase = "亚瑟";
// 多态测试:基类指针指向派生类对象
cout << "\n===== 峡谷对战 =====" << endl;
Hero* hero1 = &luBan;
Hero* hero2 = &daJi;
heroFight(hero1);
heroFight(hero2);
// 运算符重载测试:[]访问英雄属性
cout << "\n===== 英雄属性查询 =====" << endl;
heroInfo(houYi);
// 复制构造测试:引用传递vs值传递
cout << "\n===== 英雄复制 =====" << endl;
heroInfo(luBan); // 引用传递,不触发复制构造
heroCopy(luBan); // 值传递,触发复制构造
// 动态申请对象:虚析构测试
cout << "\n===== 远程召唤英雄 =====" << endl;
Hero* hero3 = new Archer("伽罗", 3600, 500, "射手", 1000);
heroFight(hero3);
delete hero3; // 虚析构保证派生类+基类均析构
cout << "\n===== 峡谷闭营 =====" << endl;
cout << "当前峡谷剩余射手数量:" << Archer::getArcherCount() << endl;
return 0;
}拓展注释
函数重载
同一变量名,利用参数的类型或个数不同确定实际调用哪一个
void func1(){
cout << “hello”;
}
void func1(int n){
cout << "world";
}此时调用func1(), 输出hello; 调用func1(3), 输出world。
面向对象中类构造函数的重载也是同理。
多态
多态指的是面向对象编程时,有继承关系的不同对象对同一成员做出不同反应。
编译时多态:主要通过函数、运算符重载实现
运行时多态:主要通过虚函数 + 继承
虚函数
基类声明对象时加 virtual 前缀,主要用于基类指针指向子类对象时,非需函数调用的还是基类版本,而虚函数的话就可以正确调用重载版本
#include <iostream>
using namespace std;
class Hero {
public:
// 1. 非虚函数:静态绑定,子类无法多态重写
void normalFunc() {
cout << "Hero-非虚函数(基础行为)" << endl;
}
// 2. 普通虚函数:动态绑定,子类可选重写
virtual void virtualFunc() {
cout << "Hero-普通虚函数(默认行为)" << endl;
}
// 3. 纯虚函数:动态绑定,子类必须重写(无默认实现)
virtual void pureVirtualFunc() = 0;
};
// 派生类:实现纯虚函数,重写普通虚函数,不处理非虚函数
class Archer : public Hero {
public:
// 重写普通虚函数(可选)
void virtualFunc() override {
cout << "Archer-重写普通虚函数(射手专属行为)" << endl;
}
// 必须重写纯虚函数(否则Archer是抽象类,无法实例化)
void pureVirtualFunc() override {
cout << "Archer-实现纯虚函数(射手核心技能)" << endl;
}
// 子类同名非虚函数:仅隐藏基类版本,无多态
void normalFunc() {
cout << "Archer-隐藏基类非虚函数" << endl;
}
};
int main() {
Hero* p = new Archer(); // 基类指针指向子类对象
// 1. 非虚函数:静态绑定,执行基类版本
p->normalFunc();
// 2. 普通虚函数:动态绑定,执行子类重写版本
p->virtualFunc();
// 3. 纯虚函数:动态绑定,执行子类实现版本
p->pureVirtualFunc();
delete p;
return 0;
}输出结果(核心对比)
Hero-非虚函数(基础行为)
Archer-重写普通虚函数(射手专属行为)
Archer-实现纯虚函数(射手核心技能)核心总结(3个关键点)
- 非虚函数:基类指针调用时,只看指针类型(
Hero*),永远执行基类版本; - 普通虚函数:基类指针调用时,看实际对象类型(
Archer),执行子类重写版本(子类可选不重写,用基类默认); - 纯虚函数:子类必须实现,否则无法实例化,调用逻辑同普通虚函数(动态绑定)。
评论已关闭