自学内容网 自学内容网

C++ -class

博客主页:【夜泉_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语言初学者,如果你有任何疑问或建议,欢迎随时留言讨论!让我们一起学习,共同进步!


原文地址:https://blog.csdn.net/2401_86587256/article/details/143811514

免责声明:本站文章内容转载自网络资源,如本站内容侵犯了原著者的合法权益,可联系本站删除。更多内容请关注自学内容网(zxcms.com)!