C++实体系统:如何在保留封装性的前提下修改父类保护成员变量
问题:在不使用公共Setter函数、保留封装性的前提下修改Enemy类的保护成员
我正在测试一个基础实体系统,以下是Entity.h中的代码:
class Enemy { public: void attack(Player player); virtual void die(); protected: //信息变量 int attackDamage; std::string name; bool alive; }; class ChildEnemy1 : public Enemy { name = "Enemy1" //无效 }; class ChildEnemy2 : public Enemy { name = "Enemy2" //无效 };
请问如何在不使用公共Setter函数、保留封装性的前提下,修改attackDamage、name、alive这些信息变量?
好的,咱们来解决这个问题——你现在的核心需求是在不破坏封装(不用公共Setter)的情况下,让派生类能正确初始化或修改基类的保护成员,对吧?首先得提一句:你之前代码里直接在派生类的类体里写name = "Enemy1"是语法错误,类体里只能声明成员,不能直接执行赋值操作,得在函数内部或者初始化列表里处理。
下面给你几个符合C++规范且能完美保留封装性的方案:
方案1:给基类添加受保护的构造函数,派生类通过初始化列表调用
这是最常用也最贴合封装原则的方式。你可以在Enemy类里定义受保护的构造函数,只允许派生类调用它来初始化基类的成员:
class Enemy { public: void attack(Player player); virtual void die(); protected: // 受保护构造函数:外部无法调用,只有派生类和基类自身能使用 Enemy(int damage, const std::string& enemyName, bool isAlive) : attackDamage(damage), name(enemyName), alive(isAlive) {} //信息变量 int attackDamage; std::string name; bool alive; }; class ChildEnemy1 : public Enemy { public: // 派生类构造函数通过初始化列表调用基类的受保护构造函数 ChildEnemy1() : Enemy(10, "Enemy1", true) {} }; class ChildEnemy2 : public Enemy { public: ChildEnemy2() : Enemy(15, "Enemy2", true) {} };
这种方式既挡住了外部代码直接操作基类成员的路径,又让派生类能合法完成初始化,完全符合封装的要求。
方案2:添加受保护的初始化/修改函数
如果需要在对象创建之后修改这些成员(比如敌人受伤后切换alive状态,或者升级后调整attackDamage),可以在基类里定义受保护的成员函数,让派生类通过这些函数来修改:
class Enemy { public: void attack(Player player); virtual void die(); protected: // 无参构造函数(如果需要默认创建对象) Enemy() : attackDamage(0), name(""), alive(false) {} // 受保护的修改函数:只有派生类和基类能调用 void updateAttackDamage(int newDamage) { attackDamage = newDamage; } void setEnemyName(const std::string& newName) { name = newName; } void toggleAliveStatus(bool isAlive) { alive = isAlive; } int attackDamage; std::string name; bool alive; }; class ChildEnemy1 : public Enemy { public: ChildEnemy1() { // 在派生类构造函数里调用受保护函数完成初始化 updateAttackDamage(10); setEnemyName("Enemy1"); toggleAliveStatus(true); } // 比如派生类的自定义方法里也能修改 void takeDamage(int damage) { attackDamage -= damage; if (attackDamage <= 0) { toggleAliveStatus(false); die(); } } };
这里的修改函数是受保护的,外部代码根本碰不到,既满足了修改需求,又守住了封装的边界。
方案3:C++11及以后的类内成员初始化
如果基类的成员有默认值,你可以直接在基类里给成员设置默认初始化值,派生类如果需要修改,可以在自己的成员函数(比如构造函数)里直接赋值:
class Enemy { public: void attack(Player player); virtual void die(); protected: // 类内默认初始化:C++11及以后支持 int attackDamage = 0; std::string name = "Unknown Enemy"; bool alive = false; }; class ChildEnemy1 : public Enemy { public: ChildEnemy1() { // 派生类的成员函数里可以直接修改基类的保护成员 attackDamage = 10; name = "Enemy1"; alive = true; } };
注意:这种直接赋值的操作只能在函数内部进行,不能像你之前那样在类体里直接写赋值语句——那是不符合C++语法的。
内容的提问来源于stack exchange,提问作者ciaran wickham
相关产品推荐
相关产品推荐

