博客主页:【夜泉_ly】
本文专栏:【C++】
欢迎点赞👍收藏⭐关注❤️
文章目录
- 💥 结构体独自升级
- 🔄 转职,暗影君王
- 👤 出现,影子士兵
- ⚔️ 站起来,耶格利特
- 👑 技能,君王领域
- 💀 召唤,暗影军团
💥 结构体独自升级
在C语言中,结构体是个自定义类型,大概长这么个样子:struct Node { int _data; struct Node* _pNext; }
而在C++中,我们可以这样写: struct Node { int _data; Node* _pNext; }
这段代码在C语言中会报错:
而在C++中却能正常运行,为什么?因为C++的结构体升级了!
从最弱猎人到暗影君王,来看看我们的程肖宇/ struct 发生了怎样的变化吧。
🔄 转职,暗影君王
sturct ChengXiaoYu{char[10] _name;
};
C++ 中,引入了类 class
的概念。而 struct
也被升级,多了很多的东西,但总体来说,升级后的struct
与 类class
区别不大,一般我们更喜欢使用 class
:
class ChengXiaoYu{char[10] _name;
};
结构体里面可以声明其他结构体,类里面当然也可以声明其他的类,比如 string
:
class ChengXiaoYu{string _name;
};
👤 出现,影子士兵
在 C++ 的类和结构体中,有个叫做访问限定符的东西,长这么个样子:
public:
private:
protected:
干什么的呢?当然是用来限定访问的。
来个影子士兵类:
class ShadowSoldier {string _name;int _level;
};
再来个影子士兵:
void Test() { ShadowSoldier soldier1; }
现在我想提取这个影子士兵(访问成员变量),会发生什么?
soldier1._name;
而如果将影子士兵类改成结构体:
class ShadowSoldier {string _name;int _level;
};
这就是 struct 与 class 最主要的不同点:
在C++中,结构体的成员默认是 public
的,这意味着它们可以直接被外部访问。类的成员默认是 private
的,这意味着它们不能被外部直接访问。
如果想让影子士兵类的成员可以被外界访问,可以加个访问限定符 public
:
class ShadowSoldier {
public:string _name;int _level;
};
我们的暗影君王不想让其他人知道他的名字,可以加个访问限定符 private
:
class ChengXiaoYu{
private:string _name = "程肖宇";
};
至于 protect
,在继承和多态以前就暂时认为和 private
一样吧。
⚔️ 站起来,耶格利特
新技能,保存影子,程肖宇得到了一片空间:
class ChengXiaoYu {
private:vector<ShadowSoldier> _shadowSoldiers; // 保存影子士兵string _name = "程肖宇";
};
新技能,提取影子,程肖宇多了个成员函数:
等等。。成员函数?C语言的 struct 只能声明成员变量,C++还能定义函数?
当然可以!只要有系统,什么都是可能的。
class ChengXiaoYu {
public:void extractShadow(const ShadowSoldier& soldier) {_shadowSoldiers.push_back(soldier);cout << "[" << soldier._name << " Level " << soldier._level << "]" << endl;}
private:vector<ShadowSoldier> _shadowSoldiers; // 保存影子士兵string _name = "程肖宇";
};
来看看如何使用新技能:
void Test()
{ChengXiaoYu chengXiaoYu;ShadowSoldier soldier;soldier._level = 7;soldier._name = "耶格利特";chengXiaoYu.extractShadow(soldier);
}
运行结果:
程肖宇在多次使用技能后已经很熟练了,只需要个口令(声明)就能使用:
class ChengXiaoYu {
public:void extractShadow(const ShadowSoldier& soldier);
private:vector<ShadowSoldier> _shadowSoldiers; // 保存影子士兵string _name = "程肖宇";
};
定义可以放在类外:
void extractShadow(const ShadowSoldier& soldier) {shadowSoldiers.push_back(soldier);cout << "[" << soldier.name << " Level " << soldier.level << "]" << endl;
}
但这时又出错了:
因为如果将技能的定义放在类外,必须说明这是程肖宇的专属技能(指定类域):
void ChengXiaoYu::extractShadow(const ShadowSoldier& soldier) {shadowSoldiers.push_back(soldier);cout << "[" << soldier.name << " Level " << soldier.level << "]" << endl;
}
是的,这也是和 C 语言的一个很大的区别,C++ 的 struct 和 class 是有个域的。
👑 技能,君王领域
在刚刚使用技能时,程肖宇有传自己的信息吗?
chengXiaoYu.extractShadow(soldier);
好像只传了待提取的影子士兵?
这其实是个新技能:君王领域——在施术者使用技能时,可以少传一个参数😜。
简单讲,系统又开后门了,当施术者使用技能时,施术者的意识会被系统转化成一个 this
指针。通过 this
指针,施术者(即程序)可以明确知道自己正在操作哪个影子(对象),确保所有的技能(成员函数)都能在正确的对象上执行。
类似于这样:
void extractShadow(ChengXiaoYu * const this, const ShadowSoldier& soldier) {
所以在技能中直接将施术者的意识具象化也是可以的:
this->shadowSoldiers.push_back(soldier);
但是,永远别想改变施术者的意识,系统不会允许的:
this = nullptr;
💀 召唤,暗影军团
我们先将影子士兵的类改造一下,加个初始化,加个打印:
class ShadowSoldier {
public:ShadowSoldier (const string& name, int level) { _name = name; _level = level; }void display() const { cout << "[" << _name << " Level " << _level << "]" << endl; }
private:string _name;int _level;
};
再将程肖宇的类改改:
class ChengXiaoYu {
public:void extractShadow(const ShadowSoldier& soldier) { _shadowSoldiers.push_back(soldier); }void displayShadowSoldiers() const {cout << "Shadow Soldiers:" << endl;for (const auto& soldier : _shadowSoldiers)soldier.display();}
private:vector<ShadowSoldier> _shadowSoldiers; // 保存影子士兵string _name = "程肖宇";
};
void Test()
{ChengXiaoYu chengXiaoYu;ShadowSoldier soldier1("伯利昂", 100);ShadowSoldier soldier2("耶格利特", 92);ShadowSoldier soldier3("贝尔", 87);ShadowSoldier soldier4("尖牙", 75);ShadowSoldier soldier5("凯瑟", 78);chengXiaoYu.extractShadow(soldier1);chengXiaoYu.extractShadow(soldier2);chengXiaoYu.extractShadow(soldier3);chengXiaoYu.extractShadow(soldier4);chengXiaoYu.extractShadow(soldier5);chengXiaoYu.displayShadowSoldiers();
}
运行结果:
现在程肖宇有了他的暗影军团,我们也来看看他多了哪些军团相关的技能吧。
技能:提取影子。暗影军团有很多人,但他们都通过同一个技能被程肖宇提取的。
因此,技能是属于系统的,技能不是属于每个人的,每个人有的只是使用技能的权力。
这个从每个人的大小就看的出来:
额,好像用了string有点看不出来。。
不管了,我们接着看:
技能:共享法力池。程肖宇有一个“共享法力池”的技能,所有影子士兵共享同一个法力池。无论哪个影子士兵消耗或补充法力,都会影响整个法力池:
class ShadowSoldier {
public:static int sharedMP;...
};
法力池不独属于任何一个士兵,因此需要在士兵类外初始化,这里给个100:
class ShadowSoldier {...
};
int ShadowSoldier::sharedMP = 100;
并且由于法力池的共享性,它也不会改变每个士兵原本的大小。
技能:共享影子指令。程肖宇有一个“共享影子指令”的技能,可以让所有的影子士兵共享同一个指令。无论哪个影子士兵调用这个指令,都会执行相同的操作。
class ShadowSoldier {
public:static void sharedCommand(const std::string& command) {if (command == "attack") {cout << "attack!!" << endl;sharedMP--;}cout << "Remaining MP: " << sharedMP << endl;}...
};
我们再让提取影子时也扣一点MP:
ShadowSoldier(const string& name, int level) { _name = name; _level = level; sharedMP--; }
测试一下:
void Test()
{ChengXiaoYu chengXiaoYu;ShadowSoldier soldier1("伯利昂", 100);ShadowSoldier soldier2("耶格利特", 92);ShadowSoldier soldier3("贝尔", 87);ShadowSoldier soldier4("尖牙", 75);ShadowSoldier soldier5("凯瑟", 78);ShadowSoldier::sharedCommand("attack");
}
因为法力池和影子指令都是共享的,所以即可以单独的影子士兵去使用,也可以整个军团去使用(类名访问)。
最后再来看个有意思的,假如有一个虚拟的程肖宇,他能不能用技能?
ChengXiaoYu* VitualCheng = nullptr;
提取影子:
void Test(){ShadowSoldier soldier("贝尔", 7);ChengXiaoYu* VitualCheng = nullptr;VitualCheng->extractShadow(soldier);
}
技能成功发动了,不过提取成功。但这至少说明系统允许虚拟的程肖宇使用技能。
如果换成虚拟的影子士兵:
void Test(){ShadowSoldier* VitualSoldier = nullptr;cout << VitualSoldier->sharedMP << endl;cout << (*VitualSoldier).sharedMP << endl;VitualSoldier->sharedCommand("attack");(*VitualSoldier).sharedCommand("attack");
}
共享法力池和共享影子指令都能用。
但不能展示个人信息:VitualSoldier->display();
总结一下,就是共享技能可以用,其他技能不能用。
希望本篇文章对你有所帮助!并激发你进一步探索编程的兴趣!
本人仅是个C语言初学者,如果你有任何疑问或建议,欢迎随时留言讨论!让我们一起学习,共同进步!