全国十大网站建设公司,网站源码免费下载分享论坛,vm虚拟化建设网站,工业互联网平台建设初始化列表C提供了初始化列表语法#xff0c;可以用于成员属性初始化。语法规则#xff1a;无参构造函数():属性1(值1), 属性2(值2), ...
{
}有参构造函数(形参1, 形参2, ...):属性1(形参1), 属性2(形参2), ...
{
}example#xff1a;写一个怪物类#xff0c;有怪物id和血量…初始化列表C提供了初始化列表语法可以用于成员属性初始化。语法规则无参构造函数():属性1(值1), 属性2(值2), ...
{
}有参构造函数(形参1, 形参2, ...):属性1(形参1), 属性2(形参2), ...
{
}example写一个怪物类有怪物id和血量属性并用初始化列表的形式初始化成员属性#include iostream
using namespace std;class Monster
{public:Monster():m_monsterId(10001), m_blood(1000){}Monster(const int monsterId, const int blood):m_monsterId(monsterId), m_blood(blood){}void print_monster_info(){cout 怪物id m_monsterId 血量 m_blood endl;}private:int m_monsterId; //怪物idint m_blood; //血量
};int main(int argc, char *argv[])
{Monster m1;m1.print_monster_info();Monster m2(10002, 2000);m2.print_monster_info();return 0;
}类对象作为类成员C中的另一个类的对象可以作为类的成员我们称为该成员为对象成员。那么这时是先构造对象成员还是先构造该类呢答案是先构造对象成员后构造该类析构函数刚好相反先析构该类后析构对象成员。example举一个有趣的例子有一个技能类一个怪物类这时怪物会有技能了所以在设计怪物类时会有技能类作为怪物类的成员。用来验证另一个类的对象作为类成员时先构造对象成员后构造该类。析构则先析构该类后析构对象成员。#include iostream
using namespace std;enum SKILL_TYPE
{SUB_DEST_BLOOD_ADD_SELF_BLOOD 0
};int g_line 0;class Monster;class Skill
{public:Skill():m_skillType(SUB_DEST_BLOOD_ADD_SELF_BLOOD), m_val(500){g_line;cout g_line 行Skill()无参构造函数被调用 endl;}Skill(const int skillType, const int val):m_skillType(skillType), m_val(val){g_line;cout g_line 行Skill(const int skillType, const int val)有参构造函数被调用 endl;}Skill(const Skill s){m_skillType s.m_skillType;m_val s.m_val;g_line;cout g_line 行Skill(const Skill s)拷贝构造函数被调用 endl;}~Skill(){g_line;cout g_line 行~Skill()析构函数被调用 endl;}//施法void spell(Monster src, Monster dest);private:int m_skillType; //技能类型int m_val;
};class Monster
{public:Monster():m_monsterId(10001), m_name(怪物), m_blood(1000), m_skill(){g_line;cout g_line 行Monster()无参构造函数被调用 endl;}Monster(const int monsterId, const string name, const int blood, const int skillType, const int skillVal):m_monsterId(monsterId), m_name(name), m_blood(blood), m_skill(skillType, skillVal){g_line;cout g_line 行Monster(const int monsterId, const string name, const int blood, const int skillType, const int skillVal)有参构造函数被调用 endl;}Monster(const Monster m){m_monsterId m.m_monsterId;m_name m.m_name;m_blood m.m_blood;m_skill m.m_skill;g_line;cout g_line 行Monster(const Monster m)拷贝构造函数被调用 endl;}void setBlood(const int blood){m_blood blood;}int getBlood(){return m_blood;}void setName(const int name){m_name name;}string getName(){return m_name;}//释放技能void spell(Monster dest){m_skill.spell(*this, dest);}~Monster(){g_line;cout g_line 行~Monster()析构函数被调用 endl;}void print_monster_info(){g_line;cout g_line 行怪物id m_monsterId 名字 m_name 血量 m_blood endl;}private:int m_monsterId; //怪物idstring m_name; //怪物名字int m_blood; //血量Skill m_skill; //技能
};//施法
void Skill::spell(Monster src, Monster dest)
{switch (m_skillType){case SUB_DEST_BLOOD_ADD_SELF_BLOOD:{//destint destBlood dest.getBlood();destBlood - m_val;if (destBlood 0)destBlood 0;dest.setBlood(destBlood);//srcint srcBlood src.getBlood();srcBlood m_val;if (srcBlood 0)srcBlood 0;src.setBlood(srcBlood);g_line;cout g_line 行 src.getName() 攻击了 dest.getName() endl;g_line;cout g_line 行 src.getName() 的血量增加到 src.getBlood() endl;g_line;cout g_line 行 dest.getName() 的血量减少到 dest.getBlood() endl;break;}default:g_line;cout g_line 行技能类型未处理 m_skillType endl;}
}int main(int argc, char *argv[])
{Monster m1(10001, 雪女, 10000, SUB_DEST_BLOOD_ADD_SELF_BLOOD, 1000);Monster m2(10002, 紫衣仙子, 20000, SUB_DEST_BLOOD_ADD_SELF_BLOOD, 2000);m1.print_monster_info();m2.print_monster_info();m1.spell(m2); return 0;
}接下来我们再根据打印结果进行代码分析Monster m1(10001, 雪女, 10000, SUB_DEST_BLOOD_ADD_SELF_BLOOD, 1000);
另一个类的对象可以作为类的成员时会先构造对象成员再构造改该类析构则刚好相反先析构
该类再析构对象成员。所以执行该语句调用构造函数的顺序为
1Skill类有参构造函数被调用
2Monster类有参构造函数被调用Monster m2(10002, 紫衣仙子, 20000, SUB_DEST_BLOOD_ADD_SELF_BLOOD, 2000);
另一个类的对象可以作为类的成员时会先构造对象成员再构造改该类析构则刚好相反先析构
该类再析构对象成员。所以执行该语句调用构造函数的顺序为
1Skill类有参构造函数被调用
2Monster类有参构造函数被调用main函数执行结束时会调用析构函数释放资源调用析构函数的顺序为
1m2被析构Monster类析构函数被调用
2m2的m_skill对象成员被析构Skill类析构函数被调用
3m1被析构Monster类析构函数被调用
4m1的m_skill对象成员被析构Skill类析构函数被调用静态成员静态成员包括静态成员变量就是在成员变量前加上关键词static修饰的成员变量所有对象共享一份数据可以通过类名进行访问Monster::ms_counter;可以通过对象进行访问Monster m; m.ms_counter;在编译阶段分配内存类内声明类外初始化有publicprotectedprivate访问权限静态成员函数就是在成员函数前加上关键字static修饰的成员函数所有对象共享同一个函数可以通过类名进行访问Monster::getMonsterCounter();可以通过对象进行访问Monster m; m.getMonsterCounter();静态成员函数的函数体内只能访问静态成员变量和静态成员函数不能访问非静态成员变量和非静态成员函数有publicprotectedprivate访问权限example:测试静态成员变量,所有对象共享一份类内声明类外初始化以及两种访问方式#include iostream
using namespace std;class Monster
{public:Monster():m_monsterId(0){ms_counter;}Monster(const int monsterId):m_monsterId(monsterId){ms_counter;}Monster(const Monster m){m_monsterId m.m_monsterId;ms_counter;}~Monster(){ms_counter--;}static int ms_counter; //怪物个数private:int m_monsterId; //怪物id
};int Monster::ms_counter 0; //静态成员类外初始化int main(int argc, char *argv[])
{//1.静态成员用类名进行访问cout ms_counter Monster::ms_counter endl;;//2.静态成员用对象进行访问Monster m1;cout ms_counter m1.ms_counter endl;Monster m2;cout ms_counter m2.ms_counter endl;return 0;
}需要注意的是静态成员变量也有publicprotectedprivate访问权限的如果我们将以上代码中的静态成员变量声明为private权限类外将不能对静态成员变量进行访问example测试静态成员函数所有对象共享一份静态成员函数的函数体内只能访问静态成员变量或静态成员函数不能访问非静态成员变量和非静态成员函数。以及两种访问方式#include iostream
using namespace std;class Monster
{public:Monster():m_monsterId(0){ms_counter;}Monster(const int monsterId):m_monsterId(monsterId){ms_counter;}Monster(const Monster m){m_monsterId m.m_monsterId;ms_counter;}~Monster(){ms_counter--;}static int getMonsterCounter(){return ms_counter;}static void setMonsterCounter(const int counter){ms_counter counter;cout ms_counter getMonsterCounter() endl;//m_monsterId 90001; //错误静态成员函数只能访问静态成员变量或静态成员函数}private:static int ms_counter; //怪物个数int m_monsterId; //怪物id
};int Monster::ms_counter 0; //静态成员类外初始化int main(int argc, char *argv[])
{//1.静态成员用类名进行访问cout ms_counter Monster::getMonsterCounter() endl;;//2.静态成员用对象进行访问Monster m1;cout ms_counter m1.getMonsterCounter() endl;Monster m2;cout ms_counter m2.getMonsterCounter() endl;return 0;
}需要注意的是静态成员函数也有publicprotectedprivate访问权限的如果我们将以上代码中的静态成员函数声明为private权限类外将不能对静态成员函数进行访问好了关于C面向对象编程之三初始化列表、类对象作为类成员、静态成员先写到这。